javascript - 相交的半透明笔画文本
问题描述
我对包含 alpha 的绘画 context.stokeText 有疑问。较大的线宽值会产生一些相交笔划的效果,因此颜色会更暗。我怎样才能避免这种情况?
ctx.strokeStyle ="rgba(0,0,0,0.3)";
ctx.lineWidth = 15;
ctx.lineJoin="round";
ctx.strokeText(text, x, y);
解决方案
这在规范中有点不一致,因为通常重叠的子路径只绘制一次。
但是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>
推荐阅读
- asp.net-mvc - Web 应用程序文件夹的权限
- android - 如何使用改造将 2 个参数传递给 GET 请求?
- react-admin - 如果react-admin中查询字段的长度很短,如何防止发送get请求
- flutter - 在颤动页面视图中动态更新内容
- react-native - 一旦状态在本机反应中发生变化,平面列表就会被隐藏
- node.js - Hyperledger Fabric 1.4:尝试连接 ChannelEventHub.connect(true) 时出错。错误:将 ChannelEventhub 连接到对等点时出错
- c# - Angularjs 正在向 API 发送空值,为什么?
- php - 如何按具有未知索引的子数组值对数组进行排序
- c - STM32 I2C 将 SDA 设置为低
- forms - 访问如何在表单上显示表的记录数