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

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

楔子

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

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

外发光效果

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

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();

效果图以下:微信

若是绘制圆形效果以下:
spa

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

内阴影

接下来的问题可能就变得有点难度。若是咱们须要以下的一个内阴影的效果呢?code

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

仍是没问题,仍是能够经过渐变来搞定,只是渐变的stop设置要麻烦一点罢了。 若是在复杂一些的图形呢,好比下面的线段效果:ip

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

如何绘制内阴影效果

要实现上面的内阴影效果,首先仍是使用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();

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

同时绘制内外阴影效果

若是修改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();

绘制的效果以下:

内阴影的缺陷

上述方法实现的内阴影颜色的颜色只能和绘制主体同样的颜色,而不能像外阴影的颜色同样,能够自由定义。 好比把上述代码中的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();

最终的效果以下图所示:

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

实现闪烁的效果

基于上面的实现,咱们能够实现一个阴影闪烁的效果,只须要不断更改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;
  }
}

···

若是作一些叠加绘制,还能够实现以下效果:

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;
      }
    }

结语

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

  1. CanvasRenderingContext2D.globalCompositeOperation
  2. CanvasRenderingContext2D.shadowBlur

其中globalCompositeOperation是一个有意思的属性,经过设置不一样的参数,能够实现不少不一样的效果。好比以下的效果就用到了这个属性:
image.png

有兴趣的读者能够关注往期更多的文章。

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

相关文章
相关标签/搜索