美文网首页
canvas可视化效果之内阴影效果

canvas可视化效果之内阴影效果

作者: ITman彪叔 | 来源:发表于2020-12-18 18:10 被阅读0次

    canvas可视化效果之内阴影效果

    楔子

    在之前的一个轨道交通可视化项目中,运用到了很多绘制技巧。 可以参考 之前的一篇文章 《利用canvas阴影功能与双线技巧绘制轨道交通大屏项目效果

    image

    效果图中的轨道,就同时存在外发光和内发光效果的效果。

    外发光效果

    我们知道外发光效果是很容易实现的,直接通过设置阴影效果即可达到。比如我们随便绘制一条线段,加上阴影效果,看起来就是外发光的效果:

          ctx.clearRect(0,0,canvas.width,canvas.height);
          ctx.shadowBlur= 20;
          ctx.shadowOffsetX = 0;
          ctx.shadowOffsetY = 0;
          ctx.shadowColor="red";
          ctx.lineCap = "round";
          ctx.lineJoin  = "round";
          ctx.lineWidth = 10;
          ctx.strokeStyle = "blue";
          ctx.beginPath();
          ctx.moveTo(300,300);
          ctx.lineTo(750,300);
          ctx.quadraticCurveTo(800,300,800,350);
          ctx.lineTo(800,450);
          ctx.quadraticCurveTo(800,500,750,500);
          ctx.lineTo(300,500);
          ctx.stroke();
    

    效果图如下:

    image

    如果绘制圆形效果如下:


    image

    上面的代码都容易理解,就是通过shadowBlur产生渐变阴影的效果。 默认的阴影,我们称之为外阴影,意思都是图像向往展开的阴影效果。

    内阴影

    接下来的问题可能就变得有点难度。如果我们需要如下的一个内阴影的效果呢?

    image

    有人说,简单,一个渐变就搞定了。 那再看看下面这个图像呢?


    image

    还是没问题,还是可以通过渐变来搞定,只是渐变的stop设置要麻烦一点罢了。 如果在复杂一些的图形呢,比如下面的线段效果:

    image

    对于上面的线段的内阴影效果,就很难使用简单的渐变来实现了。

    如何绘制内阴影效果

    要实现上面的内阴影效果,首先还是使用shadowBlur参数,然后把ctx的globalCompositeOperation参数设置为“source-out” 即可。 试试如下代码:

     ctx.globalCompositeOperation = 'source-out';
         ctx.beginPath();
         ctx.beginPath();
        ctx.moveTo(300,300);
        ctx.lineTo(750,300);
        ctx.quadraticCurveTo(800,300,800,350);
        ctx.lineTo(800,450);
        ctx.quadraticCurveTo(800,500,750,500);
        ctx.lineTo(300,500);
        ctx.lineCap = "round";
         ctx.shadowBlur =15;
         ctx.lineWidth = 20;
         ctx.shadowColor="blue";
         ctx.fillStyle = 'red';
         ctx.strokeStyle = 'red';
         ctx.stroke();
    

    最终绘制的效果就是上面的线段图的效果:

    image

    同时绘制内外阴影效果

    如果修改globalCompositeOperation为“xor”,我们还可以得到既有内阴影又有外阴影的效果。 代码如下:

     ctx.globalCompositeOperation = 'xor';
         ctx.beginPath();
         ctx.beginPath();
        ctx.moveTo(300,300);
        ctx.lineTo(750,300);
        ctx.quadraticCurveTo(800,300,800,350);
        ctx.lineTo(800,450);
        ctx.quadraticCurveTo(800,500,750,500);
        ctx.lineTo(300,500);
        ctx.lineCap = "round";
         ctx.shadowBlur =15;
         ctx.lineWidth = 20;
         ctx.shadowColor="red";
         ctx.fillStyle = 'red';
         ctx.strokeStyle = 'red';
         ctx.stroke();
    

    绘制的效果如下:


    image

    内阴影的缺陷

    上述方法实现的内阴影颜色的颜色只能和绘制主体一样的颜色,而不能像外阴影的颜色一样,可以自由定义。 比如把上述代码中的shadowColor改成blue,只有外阴影的颜色改变了:

     ctx.globalCompositeOperation = 'xor';
         ctx.beginPath();
         ctx.beginPath();
        ctx.moveTo(300,300);
        ctx.lineTo(750,300);
        ctx.quadraticCurveTo(800,300,800,350);
        ctx.lineTo(800,450);
        ctx.quadraticCurveTo(800,500,750,500);
        ctx.lineTo(300,500);
        ctx.lineCap = "round";
         ctx.shadowBlur =15;
         ctx.lineWidth = 20;
         ctx.shadowColor="red";
         ctx.fillStyle = 'red';
         ctx.strokeStyle = 'red';
         ctx.stroke();
    

    最终的效果如下图所示:


    image

    从图上可以看出只有外阴影颜色改变了,内阴影使用的本体的颜色。

    实现闪烁的效果

    基于上面的实现,我们可以实现一个阴影闪烁的效果,只需要不断更改shadowBlur的值,代码如下:
    ···
    setInterval(()=>{
    xor();
    },10)

    let shadowBlur = 5;
    let offset = 0.5;
    
    
    
    function xor(){
      ctx.clearRect(0,0,canvas.width,canvas.height);
      ctx.globalCompositeOperation = 'xor';
      ctx.shadowBlur= shadowBlur;
      ctx.shadowOffsetX = 0;
      ctx.shadowOffsetY = 0;
      ctx.shadowColor="red";
      ctx.lineCap = "round";
      ctx.lineJoin  = "round";
      ctx.lineWidth = 10;
      ctx.strokeStyle = "blue";
      ctx.beginPath();
      ctx.moveTo(300,300);
      ctx.lineTo(750,300);
      ctx.quadraticCurveTo(800,300,800,350);
      ctx.lineTo(800,450);
      ctx.quadraticCurveTo(800,500,750,500);
      ctx.lineTo(300,500);
      ctx.stroke();
      // ctx.stroke();
      
      ctx.globalCompositeOperation = 'xor';
      ctx.shadowBlur=shadowBlur / 10.0;
      ctx.shadowOffsetX=0;
      ctx.shadowOffsetY=0;
      ctx.shadowColor="blue";
      ctx.lineWidth =1;
      // ctx.stroke();
    
      shadowBlur += offset;
      if(shadowBlur > 15 || shadowBlur < 1){
        offset *= -1;
      }
    }
    

    ···


    image

    如果做一些叠加绘制,还可以实现如下效果:

       function xor(){
          ctx.clearRect(0,0,canvas.width,canvas.height);
          ctx.globalCompositeOperation = 'xor';
          ctx.shadowBlur= shadowBlur;
          ctx.shadowOffsetX = 0;
          ctx.shadowOffsetY = 0;
          ctx.shadowColor="red";
          ctx.lineCap = "round";
          ctx.lineJoin  = "round";
          ctx.lineWidth = 20;
          ctx.strokeStyle = "red";
          ctx.beginPath();
          ctx.moveTo(300,300);
          ctx.lineTo(750,300);
          ctx.quadraticCurveTo(800,300,800,350);
          ctx.lineTo(800,450);
          ctx.quadraticCurveTo(800,500,750,500);
          ctx.lineTo(300,500);
          ctx.stroke();
          // ctx.stroke();
          
          ctx.globalCompositeOperation = 'destination-out';
          ctx.shadowBlur=shadowBlur / 10.0;
          ctx.shadowOffsetX=0;
          ctx.shadowOffsetY=0;
          ctx.shadowColor="red";
          ctx.lineWidth =5;
          ctx.stroke();
    
          shadowBlur += offset;
          if(shadowBlur > 15 || shadowBlur < 1){
            offset *= -1;
          }
        }
    
    image

    结语

    至此文章已经到达尾声,我们可以总结一下绘制内阴影效果所用到的技术点

    1. CanvasRenderingContext2D.globalCompositeOperation
    2. CanvasRenderingContext2D.shadowBlur

    其中globalCompositeOperation是一个有意思的属性,通过设置不同的参数,可以实现很多不同的效果。比如如下的效果就用到了这个属性:

    image.png

    有兴趣的读者可以关注往期更多的文章。

    如果对可视化感兴趣,可以和我交流,微信541002349. 另外关注公众号“ITMan彪叔” 可以及时收到更多有价值的文章。

    相关文章

      网友评论

          本文标题:canvas可视化效果之内阴影效果

          本文链接:https://www.haomeiwen.com/subject/kpfybktx.html