【问题标题】:Creating a Gradient Path Fill JavaScript创建渐变路径填充 JavaScript
【发布时间】:2016-12-23 21:06:32
【问题描述】:

我最近一直在为一个项目添加阴影。我最终得到了我喜欢的东西,但阴影始终是纯透明的颜色。我希望它们随着它们走得更远而逐渐消失。


我目前拥有的:

我想要实现的目标:


现在我正在使用路径在 2D 画布上绘制阴影。当前的代码如下:

// Check if edge is invisible from the perspective of origin
var a = points[points.length - 1];
for (var i = 0; i < points.length; ++i, a = b)
{
    var b = points[i];

    var originToA = _vec2(origin, a);
    var normalAtoB = _normal(a, b);
    var normalDotOriginToA = _dot(normalAtoB, originToA);

    // If the edge is invisible from the perspective of origin it casts
    // a shadow.
    if (normalDotOriginToA < 0)
    {
        // dot(a, b) == cos(phi) * |a| * |b|
        // thus, dot(a, b) < 0 => cos(phi) < 0 => 90° < phi < 270°

        var originToB = _vec2(origin, b);

        ctx.beginPath();
        ctx.moveTo(a.x, a.y);
        ctx.lineTo(a.x + scale * originToA.x,
                   a.y + scale * originToA.y);
        ctx.lineTo(b.x + scale * originToB.x,
                   b.y + scale * originToB.y);
        ctx.lineTo(b.x, b.y);
        ctx.closePath();

        ctx.globalAlpha = _shadowIntensity / 2;
        ctx.fillStyle = 'black';
        ctx.fillRect(_innerX, _innerY, _innerWidth, _innerHeight);
        ctx.globalAlpha = _shadowIntensity;
        ctx.fill();
        ctx.globalAlpha = 1;

    }
}

关于如何实现这一目标的建议?任何和所有的帮助都非常感谢。

【问题讨论】:

    标签: javascript html shadow


    【解决方案1】:

    您可以在采用 CSS 过滤器的上下文上使用组合 + 新的 filter 属性,在本例中为模糊。

    您必须分几个步骤完成 - 通常这属于 3D 领域,但我们也可以通过渲染阴影贴图将其“伪造”为 2D。

    这里我们沿着一条由长度和角度、迭代次数表示的线渲染一个圆形,其中每次迭代都会增加模糊半径。阴影的强度由其颜色和不透明度决定。

    如果filter 属性在浏览器中不可用,则可以将其替换为手动模糊(有很多,例如StackBoxBlur 和我自己的rtblur),或者只是使用径向渐变。

    为了多次使用和提高速度,“缓存”或渲染到屏幕外画布,完成后合成回主画布。这将要求您根据最大模糊半径和初始半径计算大小,然后以 0° 角为中心渲染它。要绘制使用 drawImage() 和基于阴影开始变换的局部变换,然后旋转和缩放(下面未显示,因为有点过于宽泛)。

    在下面的示例中,假设在渲染阴影后将主要对象绘制在顶部。

    主函数接受以下参数:

    renderShadow(ctx, x, y, radius, angle, length, blur, iterations)
    
    // ctx - context to use
    // x/y - start of shadow
    // radius - shadow radius (assuming circle shaped)
    // angle - angle in radians. 0° = right
    // length - core-length in pixels (radius/blur adds to real length)
    // blur - blur radius in pixels. End blur is radius * iterations
    // iterations - line "resolution"/quality, also affects total end blur
    

    玩转形状、阴影颜色、模糊半径等,为您的场景找到最佳结果。

    演示

    浏览器支持filter时的结果:

    var ctx = c.getContext("2d");
    
    // render shadow
    renderShadow(ctx, 30, 30, 30, Math.PI*0.25, 300, 2.5, 20);
    
    // show main shape
    ctx.beginPath();
    ctx.moveTo(60, 30);
    ctx.arc(30, 30, 30, 0, 6.28);
    ctx.fillStyle = "rgb(0,140,200)";
    ctx.fill();
    
    function renderShadow(ctx, x, y, radius, angle, length, blur, iterations) {
    
      var step = length / iterations,         // calc number of steps
          stepX = step * Math.cos(angle),     // calc angle step for x based on steps
          stepY = step * Math.sin(angle);     // calc angle step for y based on steps
      
      for(var i = iterations; i > 0; i--) {   // run number of iterations
        ctx.beginPath();                      // create some shape, here circle
        ctx.moveTo(x + radius + i * stepX, y + i * stepY); // move to x/y based on step*ite.
        ctx.arc(x + i * stepX, y + i * stepY, radius, 0, 6.28);
     
        ctx.filter = "blur(" + (blur * i) + "px)"; // set filter property
        ctx.fillStyle = "rgba(0,0,0,0.5)";    // shadow color
        ctx.fill();
      }
      
      ctx.filter = "none";                    // reset filter
    }
    &lt;canvas id=c width=450 height=350&gt;&lt;/canvas&gt;

    【讨论】:

    • 为我工作。非常感谢!
    猜你喜欢
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多