想要实现文字的粒子话,最重要的两点是:
1.需要了解canvas的2d上下文的getImageData方法
getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。
对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:
- R - 红色 (0-255)
- G - 绿色 (0-255)
- B - 蓝色 (0-255)
- A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
color/alpha 以数组形式存在,并存储于 ImageData 对象的 data 属性中。
2.降低像素来达到粒子化
在代码中降低粒子化的操作是这样一段代码
function createRadius(data) {
ctx.clearRect(0,0,w,h) ;
for(var i = 0 ; i < data.length ; i++){
ctx.beginPath() ;
ctx.arc(data[i].x,data[i].y,Math.random()*defR,0,Math.PI*2) ;
ctx.fillStyle="rgb("+Math.random()*255+","+Math.random()*255+","+Math.random()*255+")";
ctx.closePath() ;
ctx.fill() ;
}
}
//查找不同颜色的值和位置
function findText(){
var imageData = ctx.getImageData(0,0,w,h) ;
var data = imageData.data ;
var pos = [] ;
for(var i = 0;i < w;i += gap){
for(var j = 0; j < h;j += gap){
var index = (j*w + i)*4;
if(data[index]>128){
pos.push({
x:i,
y:j
});
}
}
}
createRadius(pos) ;
}
注意的几点:1: data[index]>128的128是什么? >128说明这个像素点是有颜色的,即可见的
2: 降低像素数思想:原来100✖️100像素的图,我们如果用25✖️25来表示,那么每个像素点就会粗很多,同时粒度也会更加宽泛,之后我们如果将像素点变为圆形,最后我们就可以得到由一个个粒子“拼”出的效果。
所以:在findText方法中的gap就是一个像素集合区域的间隔,我们把这个区域中的所有像素点中取一个当做这个区域的颜色,有颜色,则将它放入一个数组,记录下这个像素点的x,y;这样每过gap个像素做一次判断,得到一个数组;最后以这个数组中的x,y来画圆!!不就粒子化了么,说的不怎么清晰,你只要将我下面的代码拷贝,运行一下,感受一下就知道怎么回事了。
代码干货:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CanvasLove</title>
<style>
#canvas{
background-color: #000;
}
</style>
</head>
<body>
<canvas id="canvas" ></canvas>
</body>
<script>
//在去除颜色的位置上画圆,就这么简单
var defR=6; //粒子的最大半径
var gap=10; //粒子间隙
var fontS=500; //文字大小
//动态文字数组
var textList=["你好","陌生人","我是","ClearLoveQ"];
var textCount=0;//文字数组计数器
var canvas = document.getElementById('canvas') ;
var ctx = canvas.getContext('2d') ;
var w = window.innerWidth;
var h = window.innerHeight;
canvas.width=w;
canvas.height=h;
//生成文字
function createText(text) {
ctx.clearRect(0,0,w,h) ;
ctx.font = fontS+'px "微软雅黑' ;
ctx.fillStyle = 'red' ;
ctx.textAlign = 'center' ;
ctx.textBaseline = 'middle' ;
ctx.fillText(text,w/2,h/2) ;
}
function createRadius(data) {
ctx.clearRect(0,0,w,h) ;
for(var i = 0 ; i < data.length ; i++){
ctx.beginPath() ;
ctx.arc(data[i].x,data[i].y,Math.random()*defR,0,Math.PI*2) ;
ctx.fillStyle="rgb("+Math.random()*255+","+Math.random()*255+","+Math.random()*255+")";
ctx.closePath() ;
ctx.fill() ;
}
}
//查找不同颜色的值和位置
function findText(){
var imageData = ctx.getImageData(0,0,w,h) ;
var data = imageData.data ;
var pos = [] ;
for(var i = 0;i < w;i += gap){
for(var j = 0; j < h;j += gap){
var index = (j*w + i)*4;
if(data[index]>128){
pos.push({
x:i,
y:j
});
}
}
}
createRadius(pos) ;
}
function drawFont(){
if(textCount==textList.length){
textCount=0;
}
createText(textList[textCount]);
textCount++;
findText();
}
setInterval(drawFont,1000);
</script>
</html>