在ECharts中看到过这种圆形扩散效果,相似css3,恰好项目中想把它用上,but我又不想引入整个echart.js文件,更重要的是想弄明白它的原理,因此本身动手。在这篇文章中咱们就来分析实现这种效果的两种方法,先上效果图:javascript
经过不断的改变圆的半径大小,不断重叠达到运动的效果,在运动的过程当中,设置当前canvas的透明度context.globalAlpha=0.95
,使得canvas上的圆逐渐透明直至为0,从而实现这种扩散、渐变的效果。css
1. 关键技术点context.globalAlpha = 0.95
; //设置主canvas的绘制透明度。
建立临时canvas来缓存主canas的历史图像,再叠加到主canvas上。html
2. 绘制过程
首先,咱们先来写一个绘制圆的方法:java
//画圆 var drawCircle = function() { context.beginPath(); context.arc(150, 100, radius, 0, Math.PI * 2); context.closePath(); context.lineWidth = 2; //线条宽度 context.strokeStyle = 'rgba(250,250,50,1)'; //颜色 context.stroke(); radius += 0.5; //每一帧半径增长0.5 //半径radius大于30时,重置为0 if (radius > 30) { radius = 0; } };
而后,咱们建立一个临时canvas用来缓存主canvas上的历史图像,设置主canvas的透明度context.globalAlpha=0.95
(关键一步),在每次调用drawCircle
方法绘制一个新圆以前都把主canvas上的图像,也就是以前的图像给绘制到临时的canvas中,等到drawCircle
方法绘制完新圆后,再把临时canvas的图像绘制回主canvas中。css3
核心代码以下:git
//建立一个临时canvas来缓存主canvas的历史图像 var backCanvas = document.createElement('canvas'), backCtx = backCanvas.getContext('2d'); backCanvas.width = width; backCanvas.height = height; //设置主canvas的绘制透明度 context.globalAlpha = 0.95; //显示即将绘制的图像,忽略临时canvas中已存在的图像 backCtx.globalCompositeOperation = 'copy'; var render = function() { //1.先将主canvas的图像缓存到临时canvas中 backCtx.drawImage(canvas, 0, 0, width, height); //2.清除主canvas上的图像 context.clearRect(0, 0, width, height); //3.在主canvas上画新圆 drawCircle(); //4.等新圆画完后,再把临时canvas的图像绘制回主canvas中 context.drawImage(backCanvas, 0, 0, width, height); };
与上一种方法相比,这种方法更加简单,一样是用到了透明度逐渐减少直到为0的原理,不一样的是这里并无建立临时canvas,而是运用了context.globalCompositeOperation
属性值source-over
和destination-in
来配合使用,查看globalCompositeOperation属性介绍github
核心代码以下:canvas
var render = function() { //默认值为source-over var prev = context.globalCompositeOperation; //只显示canvas上原图像的重叠部分 context.globalCompositeOperation = 'destination-in'; //设置主canvas的绘制透明度 context.globalAlpha = 0.95; //这一步目的是将canvas上的图像变的透明 context.fillRect(0, 0, width, height); //在原图像上重叠新图像 context.globalCompositeOperation = prev; //在主canvas上画新圆 drawCircle(); };
这里我采用的是第二种方式,将扩散、渐变效果运用到了百度地图上,感受还比较炫,查看更多demo缓存
圆形扩散动画动画
方法1、二都能实现一样的效果,若是动画绘制、操做canvas比较频繁,建议采用第一种方式,用临时canvas来缓存历史图像,效率更高。