随便谈谈用canvas来实现文字图片粒子化
声明:本文为原创文章,如需转载,请注明来源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来实现文字图片粒子化的更多相关文章
- Canvas实现文字散粒子化
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 移动端canvas文字图片合成并生成图片(canvas宽度自适应移动端屏幕)
这是我之前做的一个关于文字图片合成的代码,供大家参考,不足支出还望体谅:具体的注释在代码里都有,有什么不懂了可以留言互相交流.<!DOCTYPE html> <html lang=& ...
- js将文字填充与canvas画布再转为图片
需求:封装consul服务的webUI: 原因:展示consul的服务信息时,需要嵌套动画,由于其没有内置的icon,所以将服务name放于图片位: 分析:展示信息时采用了卡片式的服务布局,缩放式的服 ...
- c# post文字图片至服务器
最近由于项目需要实现c#提交文字及数据至服务器,因此研究了一下c# php数据传送: 下面用一个示例来演示,c# post文字+图片 ,php端接收: post提交数据核心代码(post数据提交) ? ...
- HTML5 <Canvas>文字粒子化
文字粒子化,额或者叫小圆圈化... 1 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> ...
- 微信小程序利用canvas生成海报分享图片
一 . 效果 这是借用女神照生成的分享的海报,图片来自网络. 新增了poster组件和更新图片自适应 二 . 准备 准备两张图片连接,最好是自己开发账号验证的https图片链接. 三 . 实现思路 其 ...
- jquery文字上下滚动--单行 批量多行 文字图片上下翻滚 | 多行滚动
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- navigation和tabbar上的文字.图片 自定义
[[UITabBarItem appearance] setTitleTextAttributes:@{ UITextAttributeTextColor : [UIColor blackColor] ...
- canvas代替img渲染图片
移动端用canvas代替img渲染图片,可以提高性能 var oImg = new Image(); oImg.src = url; oImg.onload = function(){ var cvs ...
随机推荐
- eclipse发布项目时,会自动还原server.xml和content.xml文件
因为Tomcat的端口冲突,导致eclipse发布项目时,失败.于是到server.xml文件中修改端口,重启使用eclipse发布项目,发现依然报端口冲突的错误,其原因时,刚才对server.xml ...
- SqlBulkCopy块拷贝数据时,不履行触发器和束缚 解决办法
在new SqlBulkCopy时,设置SqlBulkCopyOptions属性即可 SqlBulkCopy bulkCopy = new SqlBulkCopy(ConStr,SqlBulkCopy ...
- iOS -数据库网络之xml解析
XML文件有2种解析方式 1.基于文档(document) 2.基于事件(sax) 1.IOS中XML文件获取 首先要将XML导入工程中 在ViewController的按钮事件中,代码如下: ...
- 一个初学者对于MVC架构的理解
我很早之前就开始接触.NET开发,一直都在2.0的框架下,所以对于MVC这种架构,听说过,但没有具体使用过,近期和外部朋友接触时,有了解到他们公司在使用MVC这种架构,所以自己就找来相关资料了解一下M ...
- 09_Sum游戏(UVa 10891 Game of Sum)
问题来源:刘汝佳<算法竞赛入门经典--训练指南> P67 例题28: 问题描述:有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取,每次可以从左端或者右端取一个或多个数,但不能两端 ...
- python ljust,rjust,center,zfill对齐使用方法
字符串在输出时的对齐:S.ljust(width,[fillchar]) #输出width个字符,S左对齐,不足部分用fillchar填充,默认的为空格. S.rjust(width,[fillcha ...
- linux命令后台运行
有两种方式: 1. command & : 后台运行,你关掉终端会停止运行 2. nohup command & : 后台运行,你关掉终端也会继续运行 一. 简介 Lin ...
- Unity3d内置浏览器
uWebKit是一个Unity3d插件,个人认为比较强大,值得收藏啊 有图有真相: 安装以及破解说明: 1.导入资源包 2.将破解目录里的Editor复制到工程项目的Assets目录下进行覆盖 3.打 ...
- 动手学习TCP:客户端状态变迁
上一篇文章中介绍了TCP连接的建立和终止. 通过实际操作了解到,在TCP协议工作过程中,客户端和服务端都会接收或者发送特定标志的TCP数据包,然后进入不同的状态. 也就是说,TCP协议就是一个包含多种 ...
- Finger Gestures 3.1
3.x自定义手势 Finger Gestures用起来非常爽,除了有常用的手势之外,3.x的版本还增加了自定义手势! 官方Document:http://fingergestures.fatalfro ...