画布创建透明的图像蒙版 [英] Canvas create an image mask that is transparent

查看:240
本文介绍了画布创建透明的图像蒙版的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个画布,用户可以使用我创建的画笔工具绘制(在mousedown或touch)。
我希望绘图区域受到画布上的形状的限制,例如,汉字的形状。

I have a canvas where the user can draw with a brush tool I created (on mousedown or touch). I would like the drawing area to be restricted by a shape on the canvas, for example, the shape of a Chinese character.

形状不是简单的形状,所以使用CanvasRenderingContext2D.clip()不是真的一个选项?

The shape is not a simple shape, so using CanvasRenderingContext2D.clip() is not really an option?

我的下一个解决方案是将遮罩图像作为一个带有drawImage的PNG绘制到画布上,然后将CanvasRenderingContext2D.globalCompositeOperation更改为source-atop

My next solution is to draw the masking image as a PNG with drawImage onto the canvas, then change the CanvasRenderingContext2D.globalCompositeOperation to 'source-atop', so that the brush is drawn within the masking image only.

这是我所要求的 - 在画布的最后输出中,我不想看到蒙版图像。

Here is the requirement which I am stuck at - In the final output of the canvas, I do not want to see the masking image.

我可以接受将掩蔽图像设置为非常低的alpha,这是几乎不可见。

I could accept setting the masking image to a very very low alpha such that is is virtually invisible.

因此,我试图在放置图像之前设置全局alpha,然后在画笔开始绘制时恢复它。

Therefore, I tried to set the global alpha before placing the image, then restoring it when the brush starts to draw.

然而,绘制的重叠也与遮蔽图片具有相同的Alpha,但我希望它已满。

However, the overlap drawn also has the same alpha as the masking image, but I would like it to be at full.

有没有另一种方法来实现这个我不知道?

Is there another way to achieve this I am not aware of?

推荐答案

@ markE的解决方案是罚款小组预定义的字符,你可以在之前工作。

@markE's solution is fine for a small set of predefined characters, that you could work on before.

不幸的是,尽管文本是向量绘制操作,但是在画布Context2d中只有两个方法 fillText strokeText ,这不允许我们一个Path2D对象,由 剪辑( ) 方法。

Unfortunately, while texts are vector drawing operations, the only two methods in canvas Context2d are fillText and strokeText, which doesn't allow us to include texts in a Path2D object, needed by the clip() method.

所以如果你不能做这个预处理,我认为 globalCompositeOperation clip()
这将涉及使用2个画布,一个用于用户的绘图,另一个用于剪切/渲染。 (这里我甚至使用第三个剪贴蒙版,但它也可以只是一个< img> 标记与光栅png透明度)。 c> globalCompositeOperation的

So if you can't do this pre-processing, I think that globalCompositeOperation is a good alternative for clip(). This will involve the use of 2 canvases, one for the user's drawings, and the other one for the clipping/rendering. (Here I even use a third one for the clipping-mask, but it could also just be an <img> tag with a raster png with transparency).

模式 c>将仅绘制已绘制像素的新绘制像素。因此,第一个形状(剪贴蒙版)将不可见。

source-in mode of the globalCompositeOperation will only draw the newly drawn pixels where there were already pixels drawn. So the first shape (the clipping mask) won't be visible.

var ctx = canvas.getContext('2d');

// create a buffer canvas for the paintings
var paint = canvas.cloneNode(true);
var paint_ctx = paint.getContext('2d');

// create another buffer canvas for the clipping-mask
// (it could also be a raster png in an <img> tag
var clip_mask = canvas.cloneNode(true);
var clip_ctx = clip_mask.getContext('2d');

var clip = function(){
  // clear the visible canvas
  ctx.clearRect(0,0,canvas.width, canvas.height);
  // draw the clipping mask
  ctx.drawImage(clip_mask, 0,0);
  // change the gCO
  ctx.globalCompositeOperation = "source-in";
  // draw the user paintings
  ctx.drawImage(paint, 0,0);
  // always reset the default gCO
  ctx.globalCompositeOperation = "source-over";

  // show the stroke of the clipping area
  if(stroke.checked){
    strokeMask();
    }
  };

//
// The user painting methods
//

var doPaint = function(x, y){
  paint_ctx.beginPath();
  paint_ctx.arc(x-3.5, y-3.5, 7, Math.PI, -Math.PI);
  paint_ctx.fill();
  clip();
  };


canvas.onmousemove = function(evt){
  var rect = this.getBoundingClientRect();
  var x = evt.clientX-rect.left;
  var y = evt.clientY-rect.top;
  doPaint(x,y);
  };

//
// the clipping mask methods
//

// init the clipping-mask
var initClip = function(){
  clip_ctx.font = "150px sans-serif";
  clip_ctx.textBaseline = "top";
  clip_ctx.textAlign = "center";
  updateClip();
  };

// update the clipping-mask
var updateClip = function(){
  var val = char.value;
  clip_ctx.clearRect(0, 0, clip_mask.width, clip_mask.height);
  var x = (clip_mask.width/2);
  clip_ctx.fillText(val, x, 10);
  paint_ctx.clearRect(0, 0, paint.width, paint.height);
  clip();
  };

// listen to the text input
char.oninput = char.onchange = function(){
  var val = this.value;
  // restrict to 1 character
  if(val.length>1){
    this.value = val[val.length-1];
    }
  updateClip();
  };

// show the stroke of the mask
var strokeMask = function(){
  ctx.font = "150px sans-serif";
  ctx.textBaseline = "top";
  ctx.textAlign = "center";
  ctx.strokeStyle = "rgba(255,255,255,.3)";
  ctx.strokeText(char.value, canvas.width/2, 10);
  }
stroke.onchange = clip;

// lets go!
initClip();

body{background-color: skyblue;}
canvas{border:1px solid;}
input{max-width:1em;}
span{font-size:.7em;}

<input type="text" id="char" value="试"/>
<span>show the clipping-stroke</span><input type="checkbox" id="stroke" name="s"/><br>
<canvas id="canvas" width="200" height="150"></canvas>

这篇关于画布创建透明的图像蒙版的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆