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

Wesley13
• 阅读 755

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

楔子

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

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

效果图如下:

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

如果绘制圆形效果如下: canvas可视化效果之内阴影效果

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

内阴影

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

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

有人说,简单,一个渐变就搞定了。 那再看看下面这个图像呢? canvas可视化效果之内阴影效果

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

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

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

如何绘制内阴影效果

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

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

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

同时绘制内外阴影效果

如果修改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();

绘制的效果如下: canvas可视化效果之内阴影效果

内阴影的缺陷

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

最终的效果如下图所示: canvas可视化效果之内阴影效果

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

实现闪烁的效果

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

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

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

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

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

结语

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

  1. CanvasRenderingContext2D.globalCompositeOperation
  2. CanvasRenderingContext2D.shadowBlur

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

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

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
java中比较两个时间的差值
项目背景1.某篇文稿的发布时间是publishDate,例如:2020072118:00:41。2.现要求判断该篇文稿的发布时间是否在近30天之内。publicstaticlongdayDiff(DatecurrentDate,DatepublishDate){LongcurrentTimecurrentDat
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这