首页 > 解决方案 > 相交的半透明笔画文本

问题描述

我对包含 alpha 的绘画 context.stokeText 有疑问。较大的线宽值会产生一些相交笔划的效果,因此颜色会更暗。我怎样才能避免这种情况?

ctx.strokeStyle ="rgba(0,0,0,0.3)";                
ctx.lineWidth = 15;
ctx.lineJoin="round";                
ctx.strokeText(text, x, y);

图片

标签: javascriptcanvas

解决方案


这在规范中有点不一致,因为通常重叠的子路径只绘制一次

但是strokeText()确实会为每个字形创建一个形状,因此这种方法确实会自己绘制每个字形,从而创建这种可见的重叠。

为了克服这个问题,你会有点创意:

  • 首先绘制完全不透明的文本,
  • 然后用所需的 alpha 级别重新绘制生成的像素(有很多方法)。
  • 在您的场景上绘制它(或在后面绘制背景)。

这里有几种方法(还有很多其他方法):

可能是最简单的,但会消耗更多内存:使用第二个断开连接的画布:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

// create a new canvas just for the text
const canvas2 = canvas.cloneNode();
const ctx2 = canvas2.getContext("2d");
ctx2.font = "60px sans-serif";
const text = "MY TEXT";
const x = canvas.width - ctx2.measureText(text).width - 20;
const y = canvas.height - 20;
// draw it fully opaque
ctx2.lineWidth = 15;
ctx2.lineJoin="round";                
ctx2.strokeText(text, x, y);

// draw the background on the visible canvas
ctx.fillStyle = "#ffe97f";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// now draw our text canvas onto the visible one
// with the desired opacity
ctx.globalAlpha = 0.3;
ctx.drawImage(canvas2, 0, 0);
<canvas width="465" height="234"></canvas>

对内存更友好,但这需要您以不同的方向重写绘图逻辑,请使用合成

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.font = "60px sans-serif";
const text = "MY TEXT";
const x = canvas.width - ctx.measureText(text).width - 20;
const y = canvas.height - 20;

// first draw the text fully opaque
ctx.lineWidth = 15;
ctx.lineJoin="round";                
ctx.strokeText(text, x, y);

// now apply the opacity
ctx.fillStyle ="rgba(0,0,0,0.3)";
ctx.globalCompositeOperation = "source-in";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// and the background
ctx.fillStyle = "#ffe97f";
ctx.globalCompositeOperation = "destination-over";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// if you want to keep drawing "normaly"
ctx.globalCompositeOperation = "source-over";
<canvas width="465" height="234"></canvas>

两者的混合,具有不同的合成规则:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.font = "60px sans-serif";
const text = "MY TEXT";
const x = canvas.width - ctx.measureText(text).width - 20;
const y = canvas.height - 20;

// first draw the text fully opaque
ctx.lineWidth = 15;
ctx.lineJoin="round";                
ctx.strokeText(text, x, y);

// now redraw over itself with the desired opacity
ctx.globalAlpha = 0.3;
ctx.globalCompositeOperation = "copy";
ctx.drawImage(canvas, 0, 0);
ctx.globalAlpha = 1;

// and the background
ctx.fillStyle = "#ffe97f";
ctx.globalCompositeOperation = "destination-over";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// if you want to keep drawing "normaly"
ctx.globalCompositeOperation = "source-over";
<canvas width="465" height="234"></canvas>


推荐阅读