成品效果就像下面這樣,只要在<input>裡面打字,下面的canvas就會出現相應的粒子特效:
其他別人做的更厲害的版本可以參考這裡:
Text particle
不過不管是簡單還是複雜酷炫的版本,其基本原理都相同,就是利用了
Javascript的canvas,繪制了文字之後,擷取繪制了文字的canvas各pixel顏色和透明度資訊 (RGBA),進行處理後再依我們想要的效果再次重繪。
下面就來進行說明:
-
建立畫布
在頁面中建立一個<canvas>用來當做畫布
<canvas width="500" hiehgt="500"></canvas>
-
取得canvas物件後先繪制文字(text)上去
var canvas = document.querySelectorAll("canvas")[0]; var context = canvas.getContext("2d"); context.textAlign = "center"; context.font = "100px arial"; context.fillText(text, 200, 100);
-
取得canvas的RGBA資訊
var imageData = context.getImageData(0, 0, canvas.width, canvas.height).data;
其中data是一個類陣列物件,每四個一組分別代表canvas各pixel位置 Red, Green, Blue, Alpha 的值 (0~255),
例如 {R1, G1, B1, A1, R2, G2, B2 ,A2, R3, G3, B3, A3, ..........}
以此類推,pixel位置由canvas的由左至右,由上至下。
有了RGBA資訊後,我們就能來進行自已想要的粒子化處理了 - 粒子化處理
再處理前,先把canvas 清空
context.clearRect(0, 0, canvas.width, canvas.height);
接著對data取得每四組的RGBA值,其中我們不想拿取每個pixel的RGBA,
只想取得間隔為5 pixel (sampleRate ) 的 RGBA資訊,
並且檢查透明度 (Alpha),如果大於0的話,我們就用canvas繪制一個圓在相應的位置上。
如此一來,就會呈現原來的文字被間隔取樣重繪成圓圈的子效果了。
var sampleRate = 5; for (var j = 0; j < canvas.height; j += sampleRate) { for (var i = 0; i < canvas.width; i += sampleRate) { //Get RGBA data var red = imageData[(i + j * canvas.width) * 4]; var green = imageData[(i + j * canvas.width) * 4 + 1]; var blue = imageData[(i + j * canvas.width) * 4 + 2]; var alpha = imageData[(i + j * canvas.width) * 4 + 3]; if (alpha > 0) { //If alpha > 0, draw circle context.beginPath(); //context.strokeStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")"; context.fillStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")"; context.arc(i, j, 2, 0, 2 * Math.PI); context.fill(); } } }
Html :
<div>Please insert text here to see partical special effect.</div> <div><input type="text" /></div> <div><canvas width="500" hiehgt="500"></canvas></div>
Javascript :
//Text to draw var sampleText = "👚👕 H"; drawParticleText(sampleText); document.querySelectorAll("input")[0].addEventListener("input", function(event) { drawParticleText( this.value ? this.value : sampleText); }); function drawParticleText(text) { var x = 200; var y = 100; var canvas = document.querySelectorAll("canvas")[0]; var context = canvas.getContext("2d"); //clear canvas first context.clearRect(0, 0, canvas.width, canvas.height); //Draw text first context.textAlign = "center"; context.font = "100px arial"; context.fillText(text, 200, 100); //Get canvas data (RGB and alpha), //Data in imageData : [(r, g, b, a) of 1st place, (r, g, b, a) of 2nd place......] //from left to right, from top to bottom var imageData = context.getImageData(0, 0, canvas.width, canvas.height).data; //Clear drawing context.clearRect(0, 0, canvas.width, canvas.height); //Sampling rate var sampleRate = 5; for (var j = 0; j < canvas.height; j += sampleRate) { for (var i = 0; i < canvas.width; i += sampleRate) { //Get RGBA data var red = imageData[(i + j * canvas.width) * 4]; var green = imageData[(i + j * canvas.width) * 4 + 1]; var blue = imageData[(i + j * canvas.width) * 4 + 2]; var alpha = imageData[(i + j * canvas.width) * 4 + 3]; if (alpha > 0) { //If alpha > 0, draw circle context.beginPath(); //context.strokeStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")"; context.fillStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")"; context.arc(i, j, 2, 0, 2 * Math.PI); context.fill(); } } } }
canvas { border: 1px solid blue; }
沒有留言 :
張貼留言