如何按路径而不是区域裁剪画布图像

禅宇公园

我正在制作绘画工具,其中一项功能是显示绘制路径的裁剪图像。

我绘制的路径(图片)

例如,在图片上方,白色的路径表示我已绘制的内容,就像绘制工具一样。

裁剪图像

这是路径的裁剪图像。如果查看图片,您会看到它像关闭路径一样裁剪图像,因此它裁剪了图像“区域”而不是路径。

这是代码

function crop({ image, points }) {
  return Observable.create(observer => {
    const { width, height } = getImageSize(image);
    const canvas = document.createElement('canvas') as HTMLCanvasElement;
    const context = canvas.getContext('2d');
    canvas.width = width;
    canvas.height = height;

    context.beginPath();
    points.forEach(([x, y], idx) => {
      if (idx === 0) {
        context.moveTo(x, y);
      } else {
        context.lineTo(x, y);
      }
    });
    context.clip();

    context.drawImage(image);

    ...etc
}

crop函数接收points所绘制路径的[x坐标,y坐标] []。

有没有办法只显示我绘制的路径的图像?

海道

那就是通常所说的遮罩,但是请注意,对于当前剪辑或要获得的遮罩,最好是使用合成。

画布上下文具有各种合成选项,可让您根据像素的alpha值生成复杂的合成。

const ctx = canvas.getContext('2d');
const pathes = [[]];
let down = false;
let dirty = false;
const bg = new Image();
bg.onload = begin;
bg.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Serene_Sunset_%2826908986301%29.jpg/320px-Serene_Sunset_%2826908986301%29.jpg';

function begin() {
  canvas.width = this.width;
  canvas.height = this.height;
  ctx.lineWidth = 10;
  addEventListener('mousemove', onmousemove);
  addEventListener('mousedown', onmousedown);
  addEventListener('mouseup', onmouseup);
  anim();
  ctx.fillText("Use your mouse to draw a path", 20,50) 
}

function anim() {
  requestAnimationFrame(anim);
  if(dirty) draw();
  dirty = false;
}

function draw() {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.drawImage(bg, 0, 0);
  ctx.beginPath();
  pathes.forEach(path => {
    if(!path.length) return;
    ctx.moveTo(path[0].x, path[0].y);
    path.forEach(pt => {
      ctx.lineTo(pt.x, pt.y);
    });
  });
  // old drawings will remain on where new drawings will be
  ctx.globalCompositeOperation = 'destination-in';
  ctx.stroke();
  // reset
  ctx.globalCompositeOperation = 'source-over';
}

function onmousemove(evt) {
  if(!down) return;
  const rect = canvas.getBoundingClientRect();
  pathes[pathes.length - 1].push({
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  });
  dirty = true;
}
function onmousedown(evt) {
  down = true;
}
function onmouseup(evt) {
  down = false;
  pathes.push([]);
}
canvas {border: 1px solid}
<canvas id="canvas"></canvas>

不要犹豫,查看所有合成选项,各种情况下将需要不同的选项,例如,如果您需要绘制多个路径,则可能更喜欢先渲染路径,然后仅将图像保留在已经绘制的位置,使用该source-atop选项:

const ctx = canvas.getContext('2d');
const pathes = [[]];
pathes[0].lineWidth = (Math.random() * 20) + 0.2;
let down = false;
let dirty = false;
const bg = new Image();
bg.onload = begin;
bg.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Serene_Sunset_%2826908986301%29.jpg/320px-Serene_Sunset_%2826908986301%29.jpg';

function begin() {
  canvas.width = this.width;
  canvas.height = this.height;
  addEventListener('mousemove', onmousemove);
  addEventListener('mousedown', onmousedown);
  addEventListener('mouseup', onmouseup);
  anim();
  ctx.fillText("Use your mouse to draw a path", 20,50) 
}

function anim() {
  requestAnimationFrame(anim);
  if(dirty) draw();
  dirty = false;
}

function draw() {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  pathes.forEach(path => {
    if(!path.length) return;
    ctx.beginPath();
    ctx.lineWidth = path.lineWidth;
    ctx.moveTo(path[0].x, path[0].y);
    path.forEach(pt => {
      ctx.lineTo(pt.x, pt.y);
    });
    ctx.stroke();
  });
  // new drawings will appear on where old drawings were
  ctx.globalCompositeOperation = 'source-atop';
  ctx.drawImage(bg, 0, 0);
  
  // reset
  ctx.globalCompositeOperation = 'source-over';
}

function onmousemove(evt) {
  if(!down) return;
  const rect = canvas.getBoundingClientRect();
  pathes[pathes.length - 1].push({
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  });
  dirty = true;
}
function onmousedown(evt) {
  down = true;
}
function onmouseup(evt) {
  down = false;
  const path = [];
  path.lineWidth = (Math.random() * 18) + 2;
  pathes.push(path);
}
canvas {border: 1px solid}
<canvas id="canvas"></canvas>

还要记住,您可以很好地拥有不会添加到文档中的画布,这些画布可以用作生成真正复杂的合成的图层。drawImage()确实接受<canvas>作为源)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

画布缩放时如何裁剪图像

来自分类Dev

如何从图像画布中裁剪颜色部分?

来自分类Dev

如何在画布中对角裁剪图像

来自分类Dev

如何使用JavaScript裁剪图像的区域?

来自分类Dev

如何在画布上裁剪选定区域的位图?

来自分类Dev

画布裁剪区域和画布堆栈

来自分类Dev

如何调整大小然后使用画布裁剪图像

来自分类Dev

裁剪画布中显示的图像

来自分类Dev

如何从SD卡保存并获取图像裁剪的Android路径?

来自分类Dev

画布-裁剪不同形状的图像

来自分类Dev

图像对象裁剪并在画布中心绘制

来自分类Dev

通过画布旋转后的图像裁剪

来自分类Dev

使用画布旋转和裁剪图像

来自分类Dev

图像对象裁剪并在画布中心绘制

来自分类Dev

如何裁剪轮廓的内部区域?

来自分类Dev

如何裁剪屏幕的工作区域?

来自分类Dev

如何在画布上绘制运动图像的多条路径

来自分类Dev

找到要裁剪的图像的矩形区域

来自分类Dev

在选定区域中从uiimagepickerviewcontroller裁剪图像

来自分类Dev

使用openCV裁剪图像的区域(java)

来自分类Dev

如何从保存的base64图像中裁剪未使用的画布空间?

来自分类Dev

如何从相机裁剪图像

来自分类Dev

如何裁剪图像并保存?

来自分类Dev

如何:在裁剪区域内的SVG上获得正确的鼠标按下事件

来自分类Dev

如何优化画布图像并获得 jpg 而不是 png

来自分类Dev

如何检测图区域并从研究论文的图像中提取(裁剪)

来自分类Dev

如何在Python中裁剪和存储边界框图像区域?

来自分类Dev

如何裁剪图像的任何选定区域并将其保存到服务器?

来自分类Dev

使用画布裁剪图像 - 结果是小图像

Related 相关文章

热门标签

归档