HTML5 canvas globalAlpha 不工作

HTML5 canvas globalAlpha not working

我需要在没有 clearRect 的情况下创建平滑的透明绘图线 我尝试使用:globalAlphastrokeStyle 与 rgba 像这样:

ctx.strokeStyle = "rgba( redChannel, greenChannel, blueChannel, AlphaChannel)";

但这两种方法都不起作用。我如何在没有 clearRect 方法的情况下绘制透明线。虽然我在每张图 globalAlpha 工作之前使用 clearRect,但我需要在没有它的情况下工作。

我的代码示例:

var el = document.getElementById('c');
var ctx = el.getContext('2d');

ctx.lineWidth = 10;
ctx.lineJoin = ctx.lineCap = 'round';
ctx.globalAlpha = "0.2";
//ctx.strokeStyle = "rgba(255, 0, 0, 150)";
ctx.strokeStyle = "red";

var isDrawing, points = [ ];

el.onmousedown = function(e) {
  isDrawing = true;
  points.push({ x: e.clientX, y: e.clientY });
};

el.onmousemove = function(e) {
  if (!isDrawing) return;

  //ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  points.push({ x: e.clientX, y: e.clientY });

  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y);
  for (var i = 1; i < points.length; i++) {
    ctx.lineTo(points[i].x, points[i].y);
  }
  ctx.stroke();
  ctx.closePath();
  
};

el.onmouseup = function() {
  isDrawing = false;
  points.length = 0;
};
canvas { border: 1px solid #ccc }
<canvas id="c" width="500" height="300"></canvas>

每次鼠标移动时都会重新绘制整个路径,因此即使 globalAlpha 值设置为 0.2,分层效果也会使线条看起来很实。

选项 1: 使用 clearRect 清除路径 onmousemove 然后重绘;

选项 2: 只绘制路径的最后一段,但重叠是可见的:

var el = document.getElementById('c');
var ctx = el.getContext('2d');

ctx.lineWidth = 10;
ctx.lineJoin = ctx.lineCap = 'round';
ctx.globalAlpha = "0.2";
//ctx.strokeStyle = "rgba(255, 0, 0, 150)";
ctx.strokeStyle = "red";

var isDrawing, points = [ ];

el.onmousedown = function(e) {
  isDrawing = true;
  points.push({ x: e.clientX, y: e.clientY });
};

el.onmousemove = function(e) {
  if (!isDrawing) return;

  //ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  points.push({ x: e.clientX, y: e.clientY });

  ctx.beginPath();

  //draw just the last segment
  if(points.length>1) {
      ctx.moveTo(points[points.length-2].x, points[points.length-2].y);
      ctx.lineTo(points[points.length-1].x, points[points.length-1].y);
  }
  ctx.stroke();
  ctx.closePath();
  
};

el.onmouseup = function() {
  isDrawing = false;
  points.length = 0;
};
canvas { border: 1px solid #ccc }
<canvas id="c" width="500" height="300"></canvas>

选项 3: 设置 canvas 元素的不透明度

var el = document.getElementById('c');
var ctx = el.getContext('2d');

ctx.lineWidth = 10;
ctx.lineJoin = ctx.lineCap = 'round';
//ctx.globalAlpha = "0.2";
//ctx.strokeStyle = "rgba(255, 0, 0, 150)";
ctx.strokeStyle = "red";

var isDrawing, points = [ ];

el.onmousedown = function(e) {
  isDrawing = true;
  points.push({ x: e.clientX, y: e.clientY });
};

el.onmousemove = function(e) {
  if (!isDrawing) return;

  //ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  points.push({ x: e.clientX, y: e.clientY });

  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y);
  for (var i = 1; i < points.length; i++) {
    ctx.lineTo(points[i].x, points[i].y);
  }
  ctx.stroke();
  ctx.closePath();
  
};

el.onmouseup = function() {
  isDrawing = false;
  points.length = 0;
};
canvas { border: 1px solid #ccc; opacity:0.2; }
<canvas id="c" width="500" height="300"></canvas>

选项 3:使用两个 canvas,在 main 上 - 仅在鼠标释放时绘制,在第二个预览 canvas 上,只显示进度,所以即使在鼠标移动时绘图也将可见。同样对于预览 canvas 我们需要做一些技巧,比如清理之前的线段,所以一切看起来都不错。

//main canvas
var el = document.getElementById('c');
var ctx = el.getContext('2d');

//preview
var el2 = document.getElementById('c2');
var ctx2 = el2.getContext('2d');

ctx.lineWidth = 10;
ctx2.lineWidth = 10;
ctx.lineJoin = ctx.lineCap = 'round';
ctx2.lineJoin = ctx2.lineCap = 'round';
ctx.strokeStyle = "rgba(255, 0, 0, 0.5)";
ctx2.strokeStyle = "rgba(255, 0, 0, 0.5)";

var isDrawing, points = [ ];

el2.onmousedown = function(e) {
  isDrawing = true;
  points.push({ x: e.clientX, y: e.clientY });
  ctx.beginPath();
  ctx2.beginPath();
};

el2.onmousemove = function(e) {
  if (!isDrawing) return;
  points.push({ x: e.clientX, y: e.clientY });

  //draw just the last segment
  if(points.length>1) {
      ctx.moveTo(points[points.length-2].x, points[points.length-2].y);
      ctx.lineTo(points[points.length-1].x, points[points.length-1].y);
      
      //start preview
      ctx2.beginPath();
      //clean from last line
      ctx2.globalCompositeOperation = "destination-out";
      ctx2.strokeStyle = "rgba(255, 0, 0, 1)";
      ctx2.moveTo(points[points.length-2].x, points[points.length-2].y);
      ctx2.lineTo(points[points.length-1].x, points[points.length-1].y);
      ctx2.stroke();
      //rest
      ctx2.strokeStyle = "rgba(255, 0, 0, 0.5)";
      ctx2.globalCompositeOperation = "source-over";
      //draw new line segment
      ctx2.moveTo(points[points.length-2].x, points[points.length-2].y);
      ctx2.lineTo(points[points.length-1].x, points[points.length-1].y);
      ctx2.stroke();
  }
};

el2.onmouseup = function() {
  ctx2.clearRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);
  ctx.stroke();
  isDrawing = false;
  points.length = 0;
};
canvas { 
    border: 1px solid #ccc;
    position:absolute;
}
<canvas id="c" width="500" height="200"></canvas>
<canvas id="c2" width="500" height="200"></canvas>