介紹
在ECharts中看到過這種圓形擴散效果,類似css3,剛好項目中想把它用上,but我又不想引入整個echart.js文件,更重要的是想弄明白它的原理,所以自己動手。在這篇文章中我們就來分析實現這種效果的兩種方法,先上效果圖:
實現原理
通過不斷的改變圓的半徑大小,不斷重疊達到運動的效果,在運動的過程中,設置當前canvas的透明度context.globalAlpha=0.95
,使得canvas上的圓逐漸透明直至為0,從而實現這種擴散、漸變的效果。
實現方法一
1. 關鍵技術點context.globalAlpha = 0.95
; //設置主canvas的繪制透明度。
創建臨時canvas來緩存主canas的歷史圖像,再疊加到主canvas上。
2. 繪制過程
首先,我們先來寫一個繪制圓的方法:
//畫圓
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中。
核心代碼如下:
//創建一個臨時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屬性介紹
核心代碼如下:
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
總結
方法一、二都能實現同樣的效果,如果動畫繪制、操作canvas比較頻繁,建議采用第一種方式,用臨時canvas來緩存歷史圖像,效率更高。