【问题标题】:Intersected semi-transparent stroke text相交的半透明笔画文本
【发布时间】:2021-11-12 05:57:34
【问题描述】:

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

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

Image

【问题讨论】:

标签: javascript canvas


【解决方案1】:

这在规范中有点不一致,因为通常是overlapping sub-pathes are painted only once

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

要克服这个问题,你需要有点创意:

  • 首先绘制完全不透明的文本,
  • 然后使用所需的 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>

对内存更友好,但这需要你在不同的方向重写你的绘图逻辑,使用compositing

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    相关资源
    最近更新 更多