1. 程式人生 > >【JavaScript】explode動畫

【JavaScript】explode動畫

lte ctu 起點 運動 max cnblogs pic 位置 raw

這是一個js實現的粒子聚合文字或圖片的動畫特效

技術分享

部分程序如下

        n.container = n.container[0] || n.container;   /*有且僅有一個container*/

        var width = n.params.width;
        var height = n.params.height;
        var wWidth = document.body.clientWidth;
        var wHeight = document.body.clientHeight;

        n.container.width 
= width; n.container.height = height; var ctx = n.container.getContext(‘2d‘); var c = document.createElement(‘canvas‘); var ct = c.getContext(‘2d‘); /*用於繪制圖片或文字*/ var items = []; var picture = null; var requestId = null; var total = 0;
var getRandom = function(max, min) { min = arguments[1] || 0; return Math.floor(Math.random() * (max - min + 1) + min); /*取min和max之間的隨機數*/ }; function cutSlice() {/*cutSlice()方法,實現粒子動畫,讓其往最終位置運動*/ ctx.clearRect(0, 0, n.container.width, n.container.height);
for(var i = 0; i < c.width * c.height; i++) { var item = items[i]; var targetX = item.targetX; var targetY = item.targetY; var currentX = item.currentX; var currentY = item.currentY; var ax = false; var ay = false; if(!item.isLock) { if(Math.abs(targetX - currentX) <= .5) { item.currentX = targetX; ax = true; } else { item.currentX += (targetX - currentX) * item.ax; }; if(Math.abs(targetY - currentY) <= .5) { item.currentY = targetY; ay = true; } else { item.currentY += (targetY - currentY) * item.ay; }; if(ax && ay) {/*只有ax和ay同時到達終點時,total才會減1*/ total--; item.isLock = true; } }; var ix = item.currentX; var iy = item.currentY; ctx.putImageData(item.data, ix, iy); /*putImageData() 方法將圖像數據(從指定的 ImageData 對象)放回畫布上。*/ }; if(total > 0) { requestId = requestAnimationFrame(cutSlice); /*不用設置間隔,反復調用*/ } else { cancelAnimationFrame(requestId); }; } function Item(data, targetX, targetY, currentX, currentY) {/*創建一個Item構造函數,用來放置每一個粒子*/ this.data = data; this.targetX = targetX; /*聚合的最終位置*/ this.targetY = targetY; this.currentX = currentX;/*當前位置*/ this.currentY = currentY; this.ax = .13 - Math.random() * .06; /*ax和ay分別表示運動速度*/ this.ay = .16 - Math.random() * .08; } function drawCanvas() { if(n.params.type == 2) { /*針對圖片*/ picture = new Image(); picture.crossOrigin = ""; picture.onload = function() { var pw = picture.width; var ph = picture.height; c.width = pw; /*設置canvas的寬度*/ c.height = ph; ct.drawImage(picture, 0, 0, pw, ph, 0, 0, pw, ph); /*把圖像中的某個區域繪制到上下文中,源圖像(起點和寬高),上下文中的起點和寬高*/ draw(pw, ph); }; picture.src = n.params.img; } else { /*針對文字*/ var word = n.params.text; ct.font = ‘60px Arial‘; /*這裏指定用於測文本寬度*/ var w = ct.measureText(word).width; /*測文本寬度*/ var h = 100; c.width = w; c.height = h; ct.fillStyle = ‘deepskyblue‘; ct.font = ‘60px Arial‘; /*這裏指定用於繪制文本,應與之前設置保持一致*/ // ct.textAlign = ‘center‘; ct.textBaseline = ‘middle‘; ct.fillText(word, 0, 50); /*繪制文本,這裏為什麽沒有直接繪制上去?而要調用draw???*/ draw(w, h); } function draw(pw, ph) {/*draw 方法用來分解粒子,先分成cols 列和rows 行,每一個粒子高度都為1,然後用 getImageData() 來獲取ImageData對象,然後創建新的Item實例,然後添加到items數組中。*/ var w = 1; var h = 1; var cols = Math.floor(pw / w);/*圖片或文字的寬度高度*/ var rows = Math.floor(ph / h); for(var i = 0; i < c.width * c.height; i++) { var x = Math.floor(i % cols); /*通過xy找到每一行的所有元素(0,0)(1,0)...(0,1)(1,1)(2,1)*/ var y = Math.floor(i / cols); var data = ct.getImageData(x * w, y * h, w, h);/* 文字也能獲取??拷貝!取得原始圖像數據,要取得取數據的畫面區域的xy坐標以及該區域的像素寬度和高度,這裏每次取1*1像素*/ var vx = getRandom(300, -300); var vy = getRandom(500, -500); /*擴大範圍,使圖片周圍也有粒子*/ var item = new Item(data, x, y, x + vx, y + vy); items.push(item); }; total = items.length; cutSlice(); } }

【JavaScript】explode動畫