谈谈文字图片粒子化

  之前写了谈谈文字图片像素化,主要是为了将文字和图片像素化后的坐标提取出来,而本篇所讲即为像素化后的粒子化过程。

  先上一个简单的demo -> 粒子化demo,本篇的目的就是为了讲解怎样做这样的简单demo(大牛请无视);同时会介绍一些优秀的demo供大家参考。

 

主要思路

  首先我们谈谈粒子化的主要思路。

  像素化后(不知道怎样像素化,参考谈谈文字图片像素化),我们得到了所需图像或者文字的具体坐标,我们将它们形象地用一个个的粒子表示(这里用了圆形),得到的坐标即是粒子的最终位置。粒子的初始位置在哪里?粒子从初始位置到最终位置的运动又是如何?这些是我们可以自由发挥的。所以粒子化过程究其根本,就是怎样表示粒子的运动过程。

 

基本准备

  • canvas自适应电脑屏幕(不出现滚条):

css部分:

body {margin:0; padding:0; wdith:100%; height: 100%}
canvas {display:block; background-color:#000}

js部分:

window.canvas = document.createElement('canvas'); 
document.body.appendChild(window.canvas); 
canvas.height = window.height = window.innerHeight;
canvas.width = window.width = window.innerWidth;

 

  • 关于像素化再补充几句:

  像素化过程简单描述就是将所需的文字fillText到画布上或者将图片drawImage到画布上(设置一个离屏的canvas),然后利用getImagedata这个api将像素点提取出来。值得注意的是getImagedata并不会获取背景点的像素,所以canvas的背景使用怎样的颜色并不会影响像素点的提取。

  一般像素点的提取是根据某个像素点rgba的a值进行判断,a值的取值是0~255(rgba当做颜色属性赋值时a的取值是0~1),通常做法是判断a值非0或者半透(>125)。这里我也做了个简单的测试,当color值取black或者#000时,a值如下:

           

 

  • 关于阴影

  粒子化效果一般在黑夜最漂亮,所以背景我一般设置成黑色。如果要更带感,需要一点阴影效果。

  其实很简单,调整一下透明度即可。比如这样:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> <style type="text/css"> body {margin:0; padding:0; wdith:100%; height: 100%} canvas {display:block; background-color:#000} </style> </head> <body> <script src='http://sandbox.runjs.cn/js/sandbox/jquery/jquery-1.8.3.min.js'></script> <script src='http://hanzichi.github.io/game/Vector.js'></script> <script> // window.onload = function() { window.canvas = document.createElement('canvas'); document.body.appendChild(window.canvas); canvas.height = window.height = window.innerHeight; canvas.width = window.width = window.innerWidth; window.ctx = canvas.getContext('2d'); // } var x = 0, y = 0; setInterval(function() { ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillRect(0, 0, width,height); x+=5; y+=5; ctx.beginPath(); ctx.fillStyle = 'red' ctx.arc(x, y, 5, 0, Math.PI * 2); ctx.fill(); }, 1000 / 60) </script> </body> </html>
  当然用globalAlpha也是一样的。
 
  • 粒子具有的属性:
  将粒子放入运动场中,我们可以赋予它一些属性,比如速度,加速度,位移等等,而这些属性都可以用矢量来表示。
 

粒子运动

  之前我说过,以上皆是铺垫,运动才是粒子化的关键。因为粒子最终要汇聚成一定的形状,所以运动的某一段的终点已知,那么粒子怎样能运动到对应的位置?

  我们从最简单的直线运动说起。

 

  • 直线运动:

  谈谈文字图片像素化中用的demo就是直线运动 -> 像素化

  如何用js描述一个直线运动?首先我们要明白在怎样的情况下物体会做直线运动?学过物理我们知道速度和加速度在一条直线时,物体做直线运动。

  那么很简单,已知粒子的终点,随机粒子的起点,速度方向就确定了(起点指向终点),如果有必要,还可以设置加速度。
 
  • 曲线运动:
  仅仅做直线运动或许视觉效果太差,曲线运动会不会产生更好的视觉效果?
  什么情况下物体会做曲线运动?速度和加速度不在一条直线时,比如抛物运动。
  先看这个demo: demoHome(W·Axes) 我们取它的第一个过程进行分析,实际上就是一个二维的曲线运动。和抛物运动的不同之处是,加速度方向指向粒子的终点,为的是能够准确达到终点位置。W.Axes的另一个粒子demo也大同小异: 粒子化,相比于前一个demo只是改变了粒子的初始位置和初始速度,以及粒子运动顺序。
  我们尝试着来完成一个demo。
  前面说到,为了能使粒子能到达指定的位置,我们给了粒子一个指向指定位置的加速度,在粒子的每一帧运动中,可以将该加速度分解到x和y轴分别进行计算。比如这样:
update: function() {
  var v = this.pos2.minusNew(this.now);
  var angle = v.getAngle();
  this.v.x = (this.v.x + this.a * Math.cos(angle) / 1000 * 60) * 0.96;
  this.v.y = (this.v.y + this.a * Math.sin(angle) / 1000 * 60) * 0.96;
  this.now.x += this.v.x;
  this.now.y += this.v.y;
}

  a表示粒子的加速度值,/1000*60表示每帧的速度增加,*0.96模拟能量损失。这样的运动的话粒子通过曲线运动就能到达指定位置。

  模拟屏幕左上角到屏幕中心的曲线运动:

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> 粒子运动 </title> <style type="text/css"> body {margin:0; padding:0; wdith:100%; height: 100%} canvas {display:block; background-color:#000} </style> </head> <body bgcolor='#000'> <script src='http://hanzichi.github.io/common/vector.js'></script> <script src='http://hanzichi.github.io/common/common.js'></script> <script> window.canvas = document.createElement('canvas'); document.body.appendChild(window.canvas); canvas.height = window.height = window.innerHeight; canvas.width = window.width = window.innerWidth; window.ctx = canvas.getContext('2d'); window.vpx = width / 2; window.vpy = height / 2; var ball = { pos2: new Vector2(width/2, height/2), now: new Vector2(0, 0), r: 5, color: getRandomColor(), v: new Vector2(10, 0), a: 10, draw: function() { ctx.clearRect(0, 0, width, height); ctx.beginPath(); ctx.fillStyle = this.color; ctx.arc(this.now.x, this.now.y, this.r, 0, Math.PI * 2); ctx.fill(); }, update: function() { var v = this.pos2.minusNew(this.now); var angle = v.getAngle(); this.v.x = (this.v.x + this.a * Math.cos(angle) / 1000 * 60) * 0.96; this.v.y = (this.v.y + this.a * Math.sin(angle) / 1000 * 60) * 0.96; this.now.x += this.v.x; this.now.y += this.v.y; } }; setInterval(function() { ball.draw(); ball.update(); }, 1000 / 60); </script> </body> </html>
  当然你也可以自己设置运动函数,不过我觉得这样比较方便而已。
 
  
  • 关于缓动:
  有时为了效果我们需要设计一个缓动,什么是缓动?就是速度越来越小的运动。
  或许涉及到x和y轴同时变化的运动太过复杂,我们假设一个物体沿着x轴正方向运动,并且物体运动速度越来越小,即为缓动。
  最简单的缓动如下:
update: function() {
  var v = this.pos2.minusNew(this.now);
  v.scale(0.05);
  this.now.add(v);
}
  稍微复杂点的缓动v-s图像可以设计成二次函数或者三角函数,因为某点的切线的斜率即为速度,而切线斜率越来越小即为速度越来越小。
  更多可以参考岑安的文章 ->  【前端应该知道的那些事儿】运动学基础
 
  • 二维三维:
  三维和二维环境下的粒子化其实大同小异,不了解三维的话可以参考 rotate 3d基础试着实现一个球体的3d旋转demo。
 

关于创意

  其实粒子化本身并不难,难的是创意。这里稍微介绍几个有创意的demo。

  codepen上的一个demo,代码很长,其实实现思路也大同小异,就是变着花样的粒子的运动。

 

  同样只是粒子的运动,只是多了点创意,构造了动态文字效果。

 

总结

  文字图片粒子化其实就是粒子系统的一部分,不妨可以从最简单的一个粒子系统开始,一步步实现一个简单的粒子化demo。

  觉得不尽兴,可以参考下面更多文章:

  

  
  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值