在codepen上看到一個Canvas做的下雨效果動畫,感覺蠻有意思的。就研究了下,這裡來分享下,實現技巧。
效果截圖:
#Canvas動畫基礎
大家都知道,Canvas其實只是一個畫板。我們可以應用canvas的api在上面繪製各種圖形。
Canvas 2D 的API:https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
那麼Canvas繪製動畫的步驟就是:
繪製第一幀圖形(利用API繪圖)
清空畫板(應用程式clearRect()或fillRect())
#繪製下一幀動畫
用什麼來控制動畫每一幀的繪製時間呢?大家很容易想到 window.setInterval()和window.setTimeout()。沒錯用這兩個也可以。除此之外,後來又出現一個新的方法:window.requestAnimationFrame(callback)。
requestAnimationFrame會告訴瀏覽器你要繪製一個動畫。讓瀏覽器要重繪時呼叫你指定的方法(callback)來繪製你的動畫。
使用方法如下:
function anim() { ctx.fillStyle = clearColor; ctx.fillRect(0,0,w,h); for(var i in drops){ drops[i].draw(); } requestAnimationFrame(anim); }
一般情況下優先使用requestAnimationFrame能保持動畫繪製的頻率和瀏覽器重繪的頻率一致。不幸的是requestAnimationFrame的兼容性還不是很好。 IE9以下和addroid 4.3以下好像不支援這個屬性。不支援的瀏覽器要用setInterval或setTimeout做相容。
雨滴下墜效果
首先來講說雨滴下落的效果如何製作。雨滴其實是長方形,然後加殘影。殘影的繪製可以說是雨滴下落的關鍵。殘影是透過在前進的方向每一幀都繪製一個半透明的背景和一個長方形,然後前面繪製的圖形疊加產生的效果。由於前進方向的圖形最後繪製,所以顯得明亮,後面的圖形疊加的比較多,所以視覺上減弱。整體看起來後面的就像殘影。這裡繪製具有透明度背景是關鍵,否則產生不了疊加效果。
那麼來畫個雨滴看看。首先準備一個畫板:
html程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>霓虹雨</title> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <style type="text/css"> .bg { background: #000; overflow: hidden; } </style> </head> <body class="bg"> <canvas id="canvas-club"></canvas> <script type="text/javascript" src="raindrop.js"></script> </body> </html>
我在js檔案裡繪製動畫(raindrop.js),程式碼如下:
var c = document.getElementById("canvas-club"); var ctx = c.getContext("2d");//获取canvas上下文 var w = c.width = window.innerWidth; var h = c.height = window.innerHeight;//设置canvas宽、高 var clearColor = 'rgba(0, 0, 0, .1)';//画板背景,注意最后的透明度0.1 这是产生叠加效果的基础 function random(min, max) { return Math.random() * (max - min) + min; } function RainDrop(){} //雨滴对象 这是绘制雨滴动画的关键 RainDrop.prototype = { init:function(){ this.x = random(0, w);//雨滴的位置x this.y = 0;//雨滴的位置y this.color = 'hsl(180, 100%, 50%)';//雨滴颜色 长方形的填充色 this.vy = random(4, 5);//雨滴下落速度 this.hit = random(h * .8, h * .9);//下落的最大值 this.size = 2;//长方形宽度 }, draw:function(){ if (this.y < this.hit) { ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.size, this.size * 5);//绘制长方形,通过多次叠加长方形,形成雨滴下落效果 } this.update();//更新位置 }, update:function(){ if(this.y < this.hit){ this.y += this.vy;//未达到底部,增加雨滴y坐标 }else{ this.init(); } } }; function resize(){ w = c.width = window.innerWidth; h = c.height = window.innerHeight; } //初始化一个雨滴 var r = new RainDrop(); r.init(); function anim() { ctx.fillStyle = clearColor;//每一帧都填充背景色 ctx.fillRect(0,0,w,h);//填充背景色,注意不要用clearRect,否则会清空前面的雨滴,导致不能产生叠加的效果 r.draw();//绘制雨滴 requestAnimationFrame(anim);//控制动画帧 } window.addEventListener("resize", resize); //启动动画 anim();
漣漪效果
接著來繪製漣漪效果。與繪製雨滴的方式類似,也是透過具有透明度的背景來疊加前面的影像產生內陰影的效果。
程式碼如下(rippling.js):
var c = document.getElementById("canvas-club"); var ctx = c.getContext("2d");//获取canvas上下文 var w = c.width = window.innerWidth; var h = c.height = window.innerHeight;//设置canvas宽、高 var clearColor = 'rgba(0, 0, 0, .1)';//画板背景,注意最后的透明度0.1 这是产生叠加效果的基础 function random(min, max) { return Math.random() * (max - min) + min; } function Rippling(){} //涟漪对象 这是涟漪动画的主要部分 Rippling.prototype = { init:function(){ this.x = random(0,w);//涟漪x坐标 this.y = random(h * .8, h * .9);//涟漪y坐标 this.w = 2;//椭圆形涟漪宽 this.h = 1;//椭圆涟漪高 this.vw = 3;//宽度增长速度 this.vh = 1;//高度增长速度 this.a = 1;//透明度 this.va = .96;//涟漪消失的渐变速度 }, draw:function(){ ctx.beginPath(); ctx.moveTo(this.x, this.y - this.h / 2); //绘制右弧线 ctx.bezierCurveTo( this.x + this.w / 2, this.y - this.h / 2, this.x + this.w / 2, this.y + this.h / 2, this.x, this.y + this.h / 2); //绘制左弧线 ctx.bezierCurveTo( this.x - this.w / 2, this.y + this.h / 2, this.x - this.w / 2, this.y - this.h / 2, this.x, this.y - this.h / 2); ctx.strokeStyle = 'hsla(180, 100%, 50%, '+this.a+')'; ctx.stroke(); ctx.closePath(); this.update();//更新坐标 }, update:function(){ if(this.a > .03){ this.w += this.vw;//宽度增长 this.h += this.vh;//高度增长 if(this.w > 100){ this.a *= this.va;//当宽度超过100,涟漪逐渐变淡消失 this.vw *= .98;//宽度增长变缓慢 this.vh *= .98;//高度增长变缓慢 } } else { this.init(); } } }; function resize(){ w = c.width = window.innerWidth; h = c.height = window.innerHeight; } //初始化一个涟漪 var r = new Rippling(); r.init(); function anim() { ctx.fillStyle = clearColor; ctx.fillRect(0,0,w,h); r.draw(); requestAnimationFrame(anim); } window.addEventListener("resize", resize); //启动动画 anim();
總結
##這樣大家對整個下雨效果的製作方法,應該要有一定的了解了。 Canvas用來繪製動畫的效果確實能讓人眼睛一亮,讓web的視覺效果提升一大截。發動自己的智慧,相信能做出更多奇妙的動畫。這也是我越來越喜歡web的原因之一 O(∩_∩)O~~。 相關推薦:以上是Canvas如何實作下雨動畫實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!