javascript - 如何在具有一致不透明度的 Canvas 上进行绘制?

标签 javascript html canvas opacity

我想为我的绘画程序/应用程序中的画笔添加不透明度,因此我通过 ctx.globalAlpha 降低了不透明度,顺便说一句,我正在使用路径进行绘制。我得到了这样的东西:

片段(无绘图功能);

//context
c = document.getElementById('c').getContext("2d");

//set opacity/alpha
c.globalAlpha = 0.5

//draw lines
c.beginPath();
c.lineWidth = 20;
c.lineCap = 'round';

c.moveTo(20,20);
c.lineTo(60,20);

c.stroke();
c.beginPath();

c.moveTo(60,20);
c.lineTo(70,50);

c.stroke();
<canvas id='c'></canvas>
<style>
canvas {
  border: 1px solid black;
}
</style>

这是一个picture of it

正如您所看到的,它不是纯透明的颜色,您可以看到黑点(不好)。 那么我该如何解决 那?

最佳答案

透明度是一致的,但是这个地方你应用了两次,所以它会累积。如果仅在一条路径中出现问题,则应重复调用 moveTo/lineTo 并仅在最后抚摸。

但是我猜你想要的不止这些。解决方案是在屏幕外的 Canvas 上绘图。像这样初始化:

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

// create an offscreen canvas: this canvas is not shown on screen
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = canvas.width;
offscreenCanvas.height = canvas.height;
var oc = offscreenCanvas.getContext("2d");

然后像这样绘制/更新:

// you are drawing to the offscreen canvas
oc.beginPath();
oc.lineWidth = 20;
oc.lineCap = 'round';
oc.moveTo(20,20);
oc.lineTo(60,20);
oc.stroke();
oc.beginPath();
oc.moveTo(60,20);
oc.lineTo(70,50);
oc.stroke();

// and then copy the offscreen canvas onto your main canvas with opacity
c.globalAlpha = 0.5;
c.drawImage(offscreenCanvas, 0, 0);

当用户操作完成后(例如,中风或您需要的任何操作后),您可以清除 oc 并开始新的操作。

这也是将相同图形的多个实例绘制到一个 Canvas 上的推荐方法:在屏幕外 Canvas 上绘制一次,然后多次复制到主 Canvas 上。

更新:由于您要求“具有绘图功能”,因此我使用另一个屏幕外 Canvas 创建了一个工作绘图示例来存储用户操作之间的状态:

var canvas = document.getElementById('c');
var c = canvas.getContext("2d");

// create an offscreen canvas: this canvas is not shown on screen
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = canvas.width;
offscreenCanvas.height = canvas.height;
var oc = offscreenCanvas.getContext("2d");

// create another offscreen "freeze canvas"
var freezeCanvas = document.createElement('canvas');
freezeCanvas.width = canvas.width;
freezeCanvas.height = canvas.height;
var fc = freezeCanvas.getContext("2d");

// for visualisation purposes you can also show these canvases
//canvas.parentNode.appendChild(offscreenCanvas);
//canvas.parentNode.appendChild(freezeCanvas);

var w = 10;

var le = null;
canvas.addEventListener("mousedown", e => {
  le = e;
  sw = w;

  // at the start of a stroke clear the offscreen canvas
  oc.clearRect(0, 0, canvas.width, canvas.height);
}, false);

canvas.addEventListener("mousemove", e => {
  if (!le) return;
  
  // some primitive dynamic stroke width calculation
  var dx = e.offsetX - le.offsetX;
  var dy = e.offsetY - le.offsetY;
  var d = Math.max(1, Math.sqrt(dx*dx+dy*dy));
  sw = sw * 0.9 + (w * 4 / d) * 0.1;

  // add to your stroke image
  oc.beginPath();
  oc.lineWidth = sw;
  oc.lineCap = 'round';
  oc.moveTo(le.offsetX, le.offsetY);
  oc.lineTo(e.offsetX, e.offsetY);
  oc.stroke();
  le = e;

  // and then combine the frozen contents with the stroke
  c.clearRect(0, 0, canvas.width, canvas.height);
  c.globalAlpha = 1;
  c.drawImage(freezeCanvas, 0, 0);
  c.globalAlpha = 0.5;
  c.drawImage(offscreenCanvas, 0, 0);
}, false);

canvas.addEventListener("mouseup", e => {
  le = null;

  // and freeze the main canvas
  fc.clearRect(0, 0, canvas.width, canvas.height);
  fc.drawImage(canvas, 0, 0);
}, false);
<canvas id='c'></canvas>
<style>canvas { border: 1px solid black; }</style>

关于javascript - 如何在具有一致不透明度的 Canvas 上进行绘制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60093686/

相关文章:

android - Android中如何使用StaticLayout?

javascript - echo JS选中时的Option值

javascript - Bootstrap 具有多种形式的单一模式窗口

html - 如果隐藏滚动条,则隐藏/缩小表格的底部边框

javascript - Canvas 对象更新位置并重绘对象

c# - 大量项目在 Canvas 上的不稳定运动

javascript - if (a) b=a; 的更短表达式在 JavaScript 中

javascript - 如何在javascript中使用setter和getter,我遇到了一个错误

css - Bootstrap 4 中是否有类似 reverse sr-only 的东西?

html - 本地css文件加载,直接地址失败