canvas图片、文字粒子化
一、图片粒子化
首先看一下源图和转换成粒子效果的对比图:


左侧图片为源图,右侧图片为粒子效果图。该效果是在Canvas画布上制作的。将图片制作成粒子效果相对而言是比较简单的。重点了解两个知识点即可
1、图片是通过image对象形式绘制在画布上的,然后使用Canvas的getImageData接口,获取图像的像素信息。具体可参考菜鸟教程:getImageData
var imageData=ctx.getImageData(x, y, width, height);
参数说明:x,y为画布上的x和y坐标
width,height为获取指定区域图像的信息
返回值说明:imageData为返回值,它是一个对象,包含三个属性
imageData={
data:Unit8ClampedArray[10000] //一个包含图片区域内每个像素点的RGBA的整型数据信息
height:200 //读取的图片像素信息区域高度
width:200 //读取的图片像素信息区域宽度
}2、了解像素区域数据的排布说明,以上获取的图片数据像素信息(imageData对象中的data属性)为RGBA整型的一维数组数据。一个像素是有4个值(R,G,B,A)组成的。也就是说,数组信息每四个为一个像素点。因此,有以下规则,
第一个像素信息为:RGBA(data[0],data[1],data[2],data[3])
第二个像素信息为:RGBA(data[4],data[5],data[6],data[7])
.....
第N个像素信息为: RGBA(data[(n-1)*4],data[(n-1)*4+1],data[(n-1)*4+2],data[(n-1)*4+3])
.....
另外,像素区域既然是一个区域,它是有宽和高的。上面的推算公式适合单独一行使用定位一个像素点。所以计算像素点时要考虑到在整个图像区域内定位:
以上图为例。图像的宽和高都为200,如果按照每一个像素为一行一列时。则该图像共有200行,200列。所以要取得 i 行第 j 列的像素初始位置信息为:
var pos = (j * imageData.width + i) * 4;
其中,公式中的 i 表示行数,j 表示列数。200为图像的宽度。
下面是demo代码:呈现效果如上图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片粒子化</title>
</head>
<body>
<canvas id='canvas' width=1000 height=500 style='background-color:#000'>This browser does not support html5.</canvas>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var image = new Image();
image.src='star.png';
image.onload=function () {
context.drawImage(image, 0, 0);
getPixels();
drawPixels();
}
var pixels = []; // 存储像素数据
var space = 1; // 遗弃部分像素点
// 拾取像素点
function getPixels() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
for (var x = 0; x < imageData.width; x += space) {
for (var y = 0; y < imageData.height; y += space) {
var i = (y * imageData.width + x) * 4;
// 通过rgba中的r判断,拾取有色的图片部分
if (imageData.data[i] > 0) {
pixels.push({
x: x,
y: y,
fillStyle: 'rgba(' + imageData.data[i] + ',' + imageData.data[i + 1] + ',' + imageData.data[i + 2] + ',' + imageData.data[i + 3] + ')'
})
}
}
}
console.log(pixels.length);
}
// 将保存的像素点重新绘制
function drawPixels(){
context.clearRect(0, 0, canvas.width, canvas.height);
var scale = 2; // 缩放
var pos = {x: 100, y: 50}; // 绘制位置
for (var i = 0; i < pixels.length; i++) {
context.fillStyle = pixels[i].fillStyle;
context.fillRect(pixels[i].x * scale + pos.x + Math.random() * 10, pixels[i].y * scale + pos.y + Math.random() * 10, 1, 1);
context.fillRect(pixels[i].x + 500, pixels[i].y + 200, 1, 1);
}
}
</script>
</body>
</html>这是比较简单的基本实现,后面做下封装,再加上其他动画特效,就可以运用实际项目了。
二、文字粒子化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文字粒子化</title>
</head>
<body>
<canvas id='canvas' width=1000 height=500 style='background-color:#000'>This browser does not support html5.</canvas>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var pixels = []; // 存储像素数据
var space = 1; // 遗弃部分像素点
drawText('Canvas');
getPixels();
drawPixels();
// 拾取像素点
function getPixels() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
for (var x = 0; x < imageData.width; x += space) {
for (var y = 0; y < imageData.height; y += space) {
var i = (y * imageData.width + x) * 4;
// 通过rgba中的r判断,拾取有色的图片部分
if (imageData.data[i] > 0) {
pixels.push({
x: x,
y: y,
fillStyle: 'rgba(' + imageData.data[i] + ',' + imageData.data[i + 1] + ',' + imageData.data[i + 2] + ',' + imageData.data[i + 3] + ')'
})
}
}
}
console.log(pixels.length);
}
// 将保存的像素点重新绘制
function drawPixels(){
context.clearRect(0, 0, canvas.width, canvas.height);
var scale = 1; // 缩放
var pos = {x: 0, y: 0}; // 绘制位置
for (var i = 0; i < pixels.length; i++) {
context.fillStyle = pixels[i].fillStyle;
context.fillRect(pixels[i].x * scale + pos.x + Math.random() * 10, pixels[i].y * scale + pos.y + Math.random() * 10, 1, 1);
}
}
function drawText(text) {
context.font = "100px 微软雅黑 bold";
context.fillStyle = "rgba(168,168,168,1)";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText(text, canvas.width / 2, canvas.height / 2);
}
</script>
</body>
</html>参考:
Jeremy阳仔:Canvas + JavaScript 制作图片粒子效果
岑安:3D粒子效果
韩子迟:谈谈文字图片像素化
W·Axes:随便谈谈用canvas来实现文字图片粒子化