canvas製作動態文字顆粒動畫
阿新 • • 發佈:2018-11-12
久違的想玩下,且回顧下canva顆粒動畫製作,在codepen中找了個小案例,看了下原始碼,學習下,覺得很不錯,拿出來給大家分享下:
一、最終預覽效果:
二、核心程式碼邏輯
1. 初始化canvas畫布大小
2. canvas繪製文字,設定文字大小,文字位置
3. 繫結滑鼠事件
4. 獲取畫布內文字畫素點資料存入顆粒物件陣列
5. 更新繪製,更改 x, y的值,指定規則檢測結束狀態
三、核心程式碼
function Banner(){ var keyword = "MY LOVE"; var canvas; var context; var bgCanvas; var bgContext; var denseness = 10; //Each particle/icon var parts = []; var mouse = {x:-100,y:-100}; var mouseOnScreen = false; var itercount = 0; var itertot = 40; // 初始化canvas寬高 this.initialize = function(canvas_id){ canvas = document.getElementById_x_x(canvas_id); context = canvas.getContext('2d'); canvas.width = document.body.clientWidth; canvas.height = document.body.clientHeight; bgCanvas = document_createElement_x_x('canvas'); bgContext = bgCanvas.getContext('2d'); bgCanvas.width = canvas.width; bgCanvas.height = canvas.height; canvas.addEventListener('mousemove', MouseMove, false); canvas.addEventListener('mouseout', MouseOut, false); start(); } // 繪製文字 var start = function(){ bgContext.fillStyle = "#000"; bgContext.font = '300px impact'; bgContext.fillText(keyword, 85, 275); clear(); getCoords(); } //獲取畫布內畫素點資料 var getCoords = function(){ var imageData, pixel, height, width; imageData = bgContext.getImageData(0, 0, canvas.width, canvas.height); // console.log(imageData.data.length); //3139560 // quickly iterate over all pixels - leaving density gaps for(height = 0; height < bgCanvas.height; height += denseness){ for(width = 0; width < bgCanvas.width; width += denseness){ pixel = imageData.data[((width + (height * bgCanvas.width)) * 4) - 1]; // pixel is black from being drawn on. // 當檢索到每個畫素灰度為255不為0 -> 確定是文字區域 -> 繪製圈 if(pixel == 255) { drawCircle(width, height); } } } setInterval( update, 40 ); } // 繪製圓 var drawCircle = function(x, y){ var startx = (Math.random() * canvas.width); var starty = (Math.random() * canvas.height); var velx = (x - startx) / itertot; var vely = (y - starty) / itertot; parts.push( {c: '#' + (Math.random() * 0x949494 + 0xaaaaaa | 0).toString(16), x: x, //goal position y: y, x2: startx, //start position y2: starty, r: true, //Released (to fly free!) v: {x:velx , y: vely} } ) } // 重複繪製 var update = function(){ var i, dx, dy, sqrDist, scale; itercount++; clear(); for (i = 0; i < parts.length; i++){ //If the dot has been released if (parts[i].r == true){ //Fly into infinity!! parts[i].x2 += parts[i].v.x; parts[i].y2 += parts[i].v.y; //Perhaps I should check if they are out of screen... and kill them? } if (itercount == itertot){ parts[i].v = {x:(Math.random() * 6) * 2 - 6 , y:(Math.random() * 6) * 2 - 6}; //console.log(parts[i].v) parts[i].r = false; } //Look into using svg, so there is no mouse tracking. //Find distance from mouse/draw! dx = parts[i].x - mouse.x; dy = parts[i].y - mouse.y; sqrDist = Math.sqrt(dx*dx + dy*dy); if (sqrDist < 20){ parts[i].r = true; } //Draw the circle context.fillStyle = parts[i].c; context.beginPath(); context.arc(parts[i].x2, parts[i].y2, 4 ,0 , Math.PI*2, true); context.closePath(); context.fill(); } } //滑鼠移動事件監聽函式 var MouseMove = function(e) { if (e.layerX || e.layerX == 0) { //Reset particle positions mouseOnScreen = true; mouse.x = e.layerX - canvas.offsetLeft; mouse.y = e.layerY - canvas.offsetTop; } } // 滑鼠移除事件監聽函式 var MouseOut = function(e) { mouseOnScreen = false; mouse.x = -100; mouse.y = -100; } // 清除畫布 var clear = function(){ context.fillStyle = '#333'; context.beginPath(); context.rect(0, 0, canvas.width, canvas.height); context.closePath(); context.fill(); } } var banner = new Banner(); banner.initialize("canvas");