gpt4 book ai didi

填充具有公共(public)边框的形状后的Javascript Canvas 间隙

转载 作者:行者123 更新时间:2023-12-03 10:41:10 30 4
gpt4 key购买 nike

我想了解并学习当我使用共享边框填充两个形状/路径时遇到的问题的解决方案,即在为所有形状调用填充后,仍然有一个微小的间隙存在于他们之间。

该代码片段展示了绘制所涉及的形状/路径的代码:

ctx.beginPath();
ctx.moveTo(pBottom.x, pBottom.y);
ctx.lineTo(0, 0);
ctx.lineTo(pTop.x, pTop.y);
ctx.lineTo(pTopFront.x, pTopFront.y);
ctx.lineTo(pBottomFront.x, pBottomFront.y);
ctx.fillStyle = gradientTopSide;
ctx.fill();
ctx.fillStyle = gradientBottomSide;
ctx.fill();

ctx.beginPath();
ctx.moveTo(pBottom.x, pBottom.y);
ctx.arc(0, 0, radiusBackArc, (angleBottomBack) * Math.PI / 180, (angleTopBack) * Math.PI / 180);
ctx.lineTo(0, 0);
ctx.fillStyle = gradientBackArc;
ctx.fill();

间隙在左侧(蓝色圆圈处)、顶部和底部可见。它们是径向和线性渐变填充相遇的地方。

我想玩一点 Canvas 来创建一个简单的灯光/ torch 效果,这些线条破坏了我的乐趣。当然是因为我不知道如何在不破坏渐变效果的情况下以一种很好的方式填充它们。

Please find the JSFiddle presenting the issue.

最佳答案

当您处理涉及透明度的渐变时,您会遇到重叠,其中 Alpha channel 值会相乘,以及子像素化和点的舍入误差,也可能会出现渐变计算。

您在代码中进行的计算很可能必须正确舍入。如果不是,您将让 Canvas 对这些像素进行子像素化,并且很难保持简洁的结果,特别是在涉及 Alpha 时。这是 Canvas 的怪癖和这种绘制渐变线的方式。 Canvas 在拐 Angular 处也无法正确“弯曲”(连接),因此您会得到重叠的绘图 - 我们对此部分无能为力。

我看到有两种方法可以解决这个问题,一种简单的方式:

  • 使用您绘制的图像而不是构建形状 - 这速度很快,而且结果同样好,除非您需要不同的尺寸(如果是动画,那并不重要) 。我个人会选择这个选项(而且您也会获得更多的艺术自由)。
  • 使用不同的技术绘制形状:

我将在这里演示后者,作为奖励,您可以删除大量代码。如果你需要透明度,那么你应该选择选项 1。另外,它也不完美,因为我们仍然必须依赖 canvas 的方式来做到这一点,但当涉及到重叠问题时,它可能是一个改进的替代方案:

snapshot

  • 使用形状的单个闭合路径
  • 通过删除最后一个 lineTo() 并将其替换为 closePath() 来修改当前形状
  • 重要提示:将 lineJoin 更改为 round
  • 我们创建一个循环,在每次迭代中绘制重叠的形状 a 和 :
    • 根据迭代更改纯色
    • 稍微缩放
    • 稍微移动

我在这里做了一个简单的版本,但如果您选择使用它,我将让您自己找出更令人满意的值细节。

var d2r = Math.PI / 180, i = 0, iterations = 14;
ctx.lineJoin = "round";
ctx.lineWidth = 3;

for(; i < iterations; i++) {

ctx.beginPath();
ctx.moveTo(pBottom.x, pBottom.y);
ctx.arc(0, 0, radiusBackArc, angleBottomBack * d2r, angleTopBack * d2r);
ctx.lineTo(pTopFront.x, pTopFront.y);
ctx.arc(0, 0, radiusFrontArc, angleTopFront * d2r, angleBottomFront * d2r);
// don't set endpoint=startpoint, instead just close the shape
ctx.closePath();

// using HSL will allow us to easily set a gradient ligthness:
ctx.strokeStyle = "hsl(0, 0%, " + (i/iterations*100) + "%)";
ctx.stroke();
ctx.translate(i*0.1,-i*0.02);
ctx.scale(0.99, 0.98);
}

<强> Modified fiddle here

关于填充具有公共(public)边框的形状后的Javascript Canvas 间隙,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28773308/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com