声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢!

  看了岑安大大的教程http://www.cnblogs.com/hongru/archive/2012/03/28/2420415.html后,让我见识到了canvas操控像素能力的强大,也就自己试着做了一下。发现如此好玩的效果也正如岑安大大所说的一样,事情没有想象中那么难。

  先看个DEMO吧,先从文字下手:文字粒子化

  要做出这样的效果,只需要懂的使用canvas的getImgData()就行了。该方法能够复制画布上指定矩形的像素数据,用法很简单:

var imgData=context.getImageData(x,y,width,height);

就酱紫就可以获取到imgData。imgData是获取到的像素信息,具体如下

对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:

  • R - 红色 (0-255)
  • G - 绿色 (0-255)
  • B - 蓝色 (0-255)
  • A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)

只要是有前端编程经验的,都肯定知道rgba了,而获取到的imgData就是一个存放着制定矩形中所有像素数组的数组,第一个像素的R是imgData[0],G是imgData[1],B是imgData[2],A则是imgData[3],第二个像素的R是imgData[4],G是imgData[5],B是imgData[6],A则是imgData[7]。。。以此类推。然后,既然我们已经获取到了所有像素里的rgba参数了,我们也就可以很简单的对这些参数进行更改,然后再将更改后的imgData通过putImageData()方法贴到画布上。像素处理完毕。就是如此简单。

  知道如何获取像素数据后,接下来就可以开搞了~~~关键代码就下面这些:

function getimgData(text){
drawText(text);
var imgData = context.getImageData(0,0,canvas.width , canvas.height);
context.clearRect(0,0,canvas.width , canvas.height);
var dots = [];
for(var x=0;x<imgData.width;x+=6){
for(var y=0;y<imgData.height;y+=6){
var i = (y*imgData.width + x)*4;
if(imgData.data[i+3] >= 128){
var dot = new Dot(x-3 , y-3 , 0 , 3);
dots.push(dot);
}
}
}
return dots;
}

获取到imgData后,通过两个循环,获得透明度大于128的,也就是有颜色的像素,然后实例化一个粒子对象,存入一个粒子数组中保存,以下是粒子对象代码:

var Dot = function(centerX , centerY , centerZ , radius){
this.dx = centerX; //保存原来的位置
this.dy = centerY;
this.dz = centerZ;
this.tx = 0; //保存粒子聚合后又飞散开的位置
this.ty = 0;
this.tz = 0;
this.z = centerZ;
this.x = centerX;
this.y = centerY;
this.radius = radius;
} Dot.prototype = {
paint:function(){
context.save();
context.beginPath();
var scale = focallength/(focallength + this.z);
context.arc(canvas.width/2 + (this.x-canvas.width/2)*scale , canvas.height/2 + (this.y-canvas.height/2) * scale, this.radius*scale , 0 , 2*Math.PI);
context.fillStyle = "rgba(50,50,50,"+ scale +")";
context.fill()
context.restore();
}
}

为了让小圆扩散有3D的空间感,所以还引入了Z轴,也就是把3维平面化成二维,具体我就不多说了。可以直接戳http://www.cnblogs.com/hongru/archive/2011/09/12/2174187.html   我就是看着岑安大大的教程学的。3D效果也做好后,就做动画,随机出一个坐标,让粒子先呆在那个坐标,然后通过保存的位置再聚合,然后再随机出坐标再分散,就是这个动画的原理了。

  下面贴出所有代码:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<style>
#cas{
display: block;
border:1px solid;
margin:auto;
}
</style>
<script>
window.onload = function(){
canvas = document.getElementById("cas");
context = canvas.getContext('2d');
focallength = 250; var dots = getimgData(document.getElementById('name').value);;
var pause = false;
initAnimate();
function initAnimate(){
dots.forEach(function(){
this.x = Math.random()*canvas.width;
this.y = Math.random()*canvas.height;
this.z = Math.random()*focallength*2 - focallength; this.tx = Math.random()*canvas.width;
this.ty = Math.random()*canvas.height;
this.tz = Math.random()*focallength*2 - focallength;
this.paint();
});
animate();
} //计算帧速率
var lastTime;
var derection = true;
function animate(){
animateRunning = true;
var thisTime = +new Date();
context.clearRect(0,0,canvas.width , canvas.height);
dots.forEach(function(){
var dot = this;
if(derection){
if (Math.abs(dot.dx - dot.x) < 0.1 && Math.abs(dot.dy - dot.y) < 0.1 && Math.abs(dot.dz - dot.z)<0.1) {
dot.x = dot.dx;
dot.y = dot.dy;
dot.z = dot.dz;
if(thisTime - lastTime > 300) derection = false;
} else {
dot.x = dot.x + (dot.dx - dot.x) * 0.1;
dot.y = dot.y + (dot.dy - dot.y) * 0.1;
dot.z = dot.z + (dot.dz - dot.z) * 0.1;
lastTime = +new Date()
}
}
else {
if (Math.abs(dot.tx - dot.x) < 0.1 && Math.abs(dot.ty - dot.y) < 0.1 && Math.abs(dot.tz - dot.z)<0.1) {
dot.x = dot.tx;
dot.y = dot.ty;
dot.z = dot.tz;
pause = true;
} else {
dot.x = dot.x + (dot.tx - dot.x) * 0.1;
dot.y = dot.y + (dot.ty - dot.y) * 0.1;
dot.z = dot.z + (dot.tz - dot.z) * 0.1;
pause = false;
}
}
dot.paint();
});
if(!pause) {
if("requestAnimationFrame" in window){
requestAnimationFrame(animate);
}
else if("webkitRequestAnimationFrame" in window){
webkitRequestAnimationFrame(animate);
}
else if("msRequestAnimationFrame" in window){
msRequestAnimationFrame(animate);
}
else if("mozRequestAnimationFrame" in window){
mozRequestAnimationFrame(animate);
}
}
} document.getElementById('startBtn').onclick = function(){
if(!pause) return;
dots = getimgData(document.getElementById('name').value);
derection=true;
pause = false;
initAnimate();
}
} Array.prototype.forEach = function(callback){
for(var i=0;i<this.length;i++){
callback.call(this[i]);
}
} function getimgData(text){
drawText(text);
var imgData = context.getImageData(0,0,canvas.width , canvas.height);
context.clearRect(0,0,canvas.width , canvas.height);
var dots = [];
for(var x=0;x<imgData.width;x+=6){
for(var y=0;y<imgData.height;y+=6){
var i = (y*imgData.width + x)*4;
if(imgData.data[i] >= 128){
var dot = new Dot(x-3 , y-3 , 0 , 3);
dots.push(dot);
}
}
}
return dots;
} function drawText(text){
context.save()
context.font = "200px 微软雅黑 bold";
context.fillStyle = "rgba(168,168,168,1)";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText(text , canvas.width/2 , canvas.height/2);
context.restore();
} var Dot = function(centerX , centerY , centerZ , radius){
this.dx = centerX;
this.dy = centerY;
this.dz = centerZ;
this.tx = 0;
this.ty = 0;
this.tz = 0;
this.z = centerZ;
this.x = centerX;
this.y = centerY;
this.radius = radius;
} Dot.prototype = {
paint:function(){
context.save();
context.beginPath();
var scale = focallength/(focallength + this.z);
context.arc(canvas.width/2 + (this.x-canvas.width/2)*scale , canvas.height/2 + (this.y-canvas.height/2) * scale, this.radius*scale , 0 , 2*Math.PI);
context.fillStyle = "rgba(50,50,50,"+ scale +")";
context.fill()
context.restore();
}
}
</script>
<title>操控字体的数据</title>
</head>
<body>
<div >
<canvas id='cas' width="1000" height="500">浏览器不支持canvas</canvas>
<div style="width:150px;margin:10px auto">
<input type="text" name="" id="name" style="width:80px;" value="王鸿兴"><button id="startBtn">开始</button>
</div>
</div>
</body>
</html>

技术不是很好,代码写的不好请见谅。不过应该不难理解。

  知道文字如何粒子化后,图片也就一样的做法了。这里是另一个demo 粒子化Demo1

  源码地址:https://github.com/whxaxes/canvas-test/tree/gh-pages/src/Particle-demo/imgdata

  补充一点:过于复杂的图片不适合粒子化,因为对象过多时,对浏览器的造成很大的负荷,动画效果也就会变得很卡很卡了。一般一千个粒子左右比较合适,自己就根据图片复杂度调整粒子的大小,减少粒子数量就行了。

随便谈谈用canvas来实现文字图片粒子化的更多相关文章

  1. Canvas实现文字散粒子化

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 移动端canvas文字图片合成并生成图片(canvas宽度自适应移动端屏幕)

    这是我之前做的一个关于文字图片合成的代码,供大家参考,不足支出还望体谅:具体的注释在代码里都有,有什么不懂了可以留言互相交流.<!DOCTYPE html> <html lang=& ...

  3. js将文字填充与canvas画布再转为图片

    需求:封装consul服务的webUI: 原因:展示consul的服务信息时,需要嵌套动画,由于其没有内置的icon,所以将服务name放于图片位: 分析:展示信息时采用了卡片式的服务布局,缩放式的服 ...

  4. c# post文字图片至服务器

    最近由于项目需要实现c#提交文字及数据至服务器,因此研究了一下c# php数据传送: 下面用一个示例来演示,c# post文字+图片 ,php端接收: post提交数据核心代码(post数据提交) ? ...

  5. HTML5 <Canvas>文字粒子化

    文字粒子化,额或者叫小圆圈化... 1 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> ...

  6. 微信小程序利用canvas生成海报分享图片

    一 . 效果 这是借用女神照生成的分享的海报,图片来自网络. 新增了poster组件和更新图片自适应 二 . 准备 准备两张图片连接,最好是自己开发账号验证的https图片链接. 三 . 实现思路 其 ...

  7. jquery文字上下滚动--单行 批量多行 文字图片上下翻滚 | 多行滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. navigation和tabbar上的文字.图片 自定义

    [[UITabBarItem appearance] setTitleTextAttributes:@{ UITextAttributeTextColor : [UIColor blackColor] ...

  9. canvas代替img渲染图片

    移动端用canvas代替img渲染图片,可以提高性能 var oImg = new Image(); oImg.src = url; oImg.onload = function(){ var cvs ...

随机推荐

  1. Effective Java 20 Prefer class hierarchies to tagged classes

    Disadvantage of tagged classes 1. Verbose (each instance has unnecessary irrelevant fields). 2. Erro ...

  2. Effective Java 38 Check parameters for validity

    For public methods, use the Javadoc @throws tag to document the exception that will be thrown if a r ...

  3. 读书笔记——Windows核心编程(8)Interlocked单向链式栈

    SLists使用了无锁算法来保证原子同步,以提升系统性能,避免了诸如优先级挂和互锁的问题. 注意:所有的链表项必须对齐到MEMORY_ALLOCATION_ALIGNMENT.否则会出现奇葩的错误. ...

  4. 第三篇 :微信公众平台开发实战Java版之请求消息,响应消息以及事件消息类的封装

    微信服务器和第三方服务器之间究竟是通过什么方式进行对话的? 下面,我们先看下图: 其实我们可以简单的理解: (1)首先,用户向微信服务器发送消息: (2)微信服务器接收到用户的消息处理之后,通过开发者 ...

  5. hdu 1028 Ignatius and the Princess III(DP)

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  6. Team Foundation Server 2015(Update 1)集成 SharePoint Server 2013

    自TFS 2008开始,TFS就提供了与SharePoint Server的集成功能,通过多年的研发和提升,目前微软已经实现了两个服务器产品之间的完美集成.通过二者之间的集成,TFS服务器大幅提高和扩 ...

  7. pixel art之 hqx 算法

    在去年的时候,偶然看到hqx算法. 一个高质量的插值放大算法. 与双线性插值等插值算法相比,这个算法放大后对人眼保护相对比较好. 没有双线性插值看起来模糊,固然,也抽空把算法简单优化了一下. 官网及代 ...

  8. HDU 5102 The K-th Distance

    题意:给你n-1条边,然后没两个节点的距离按照递增的顺序,求出前k项的和. 官方题解: 把所有边(u,v) 以及(v,u)放入一个队列,队列每弹出一个元素(u,v),对于所有与u相邻的点w,如果w!= ...

  9. 2014 Super Training #4 B Problem Arrangement --状压DP

    原题:ZOJ 3777  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3777 题意:给每个题目安排在每个位置的value ...

  10. win10自动更新彻底关闭

    http://app.techweb.com.cn/wp/2016-10-24/2418646.shtml