JavaScript+Canvas实现文字粒子流特效

目录
  • 动手前思考
  • 绘制文字
  • 获取像素点位
  • 渲染粒子
  • 简单的动画效果
    • 1、随机选择四个方向中的某一个方向,生成初始坐标
    • 2、从初始位置运动到实际位置
    • 3、点击文字炸开的特效

动手前思考

首先要在特定的位置生成粒子,要获取到canvas上像素的点位,通过canvas的getImageData函数我们可以得到canvas像素点的信息,获取像素点中透明度大于0的位置。

绘制文字

新建一个canvas画布,在画布上绘制任意的文字

ctx.font = "200px Arial";
ctx.fontWeight = "900";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillStyle = "red";
ctx.fillText("稀土掘金", 0, 0);

获取像素点位

canvas的getImageData函数返回了imageData对象,该对象复制画布上指定矩形的像素数据,数组中四个值一组存放像素的RGBA信息,其中A代表透明度,当透明度大于0时表示该位置上可以生成粒子。

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

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

也就是

red=imgData.data[0];
green=imgData.data[1];
blue=imgData.data[2];
alpha=imgData.data[3];

调用getImageData函数,有4个参数,x/y表示开始复制的左上角位置的xy坐标,width/height表示将要复制的矩形区域的宽度和高度。

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

imageData对象信息如下:

如果绘制文字较小最好截取所在矩形位置,以减少获取的data数组。获取canvas绘制文字的宽度方法如下:

const { width } = ctx.measureText(this.text);

遍历数组,得到可用像素点:

  • 4组一个像素点,gap表示点的间隔,我们只获取A的位置。
  • wl表示canvas宽度,矩形像素格子排满宽度后会换行,由此可以计算出点位的xy坐标。因为四个组合一个点,所以wl要乘以4。
const gap = 4;
for (let i = 0, wl = this.canvas.width * gap; i < length; i += gap) {
    if (data[i + gap - 1]) {
      // 根据透明度判断
      const x = (i % wl) / gap;
      const y = parseInt(i / wl);
      this.textPoints.push([x, y]);
    }
}

渲染粒子

获取到像素点位textPoints数据之后就可以开始渲染粒子了

  • 新建一个画布,隐藏获取像素点的画布,在这个新的画布上绘制粒子
  • 设置粒子的半径为5,间隔10个点位生成一个粒子
  • 粒子的颜色随机生成,最终得到如下图:

let startX;
let startY;
const points = [];
for (let i = 0; i < this.textPoints.length; i++) {
    let point = this.textPoints[i];
    let x = point[0];
    let y = point[1];
    const radius = 5;
    // const radius = Math.random() * 10; // 随机生成粒子宽度
    const color = parseInt(Math.random() * 0xffffff).toString(16); // 随机生成粒子颜色
    const { x: x0, y: y0 } = this.adjustPoint(x, y); // 矫正粒子相对于画布所在位置
    if (i == 0 || ((x - startX) % 10 == 0 && (y - startY) % 10 == 0)) {
      startX = x;
      startY = y;
      const params = { x: x0 + radius, y: y0, radius, color };
      points.push(params);
    }
}

优化展示效果

  • 为了让生成的文字更好看,我们可以随机设置粒子的半径
  • 为了避免后面生成的粒子总是挡住前面粒子,我们可以随机生成粒子的顺序
  • adjustPoint函数让粒子在新画布中居中展示
this.points = points.sort((a, b) => (Math.random() > 0.5 ? -1 : 1)); // 随机排序
adjustPoint(x, y) {
  const { width, height } = this.canvasLizi;
  return {
    x: x + (width - this.textWidth) / 2,
    y: y + (height - this.textSize) / 2,
  };
}

简单的动画效果

  • 粒子从上下左右四个方向随机生成,汇聚到画布中心点
  • 点击文字时,粒子出现炸开的特效

1、随机选择四个方向中的某一个方向,生成初始坐标

  • 从左边进入画布初始坐标为(0,y),从右边进入画布初始坐标为(canvasWidth, y),y是随机数
  • 从上边进入画布初始坐标为(x,0),从下边进入画布初始坐标为(x,canvasHeight),x是随机数
for (let item of this.points) {
    let direction;
    const num = Math.random() * 1;
    if (num < 0.25) {
      direction = "left";
      item.initX = 0;
      item.initY = Math.random() * height;
    } else if (num < 0.5) {
      direction = "right";
      item.initX = width;
      item.initY = Math.random() * height;
    } else if (num < 0.75) {
      direction = "top";
      item.initX = Math.random() * width;
      item.initY = 0;
    } else {
      direction = "bottom";
      item.initX = Math.random() * width;
      item.initY = height;
    }
}

2、从初始位置运动到实际位置

  • 计算实际点与运动点之间的坐标差offsetX,offsetY
  • 判断差值是正数还是负数,当x差值为正数,则每次运动的速率为正,否则为负;当y差值为正数,则每次运动的速率为正,否则为负。
  • 计算每次运动的增量或减量。因为初始坐标和实际坐标连线可能是一条斜线,当x增加或减少一定数值,y值增量或减量等于x增量或减量乘以斜率。
animatDot() {
  if (!this.points.find((item) => item.hasOwnProperty("initX"))) {
    // 当不存在运动点时取消动画
    cancelAnimationFrame(this.animatDot.bind(this));
    return;
  }
  this.points.forEach((item) => {
    const offsetX = item.x - item.initX;
    const offsetY = item.y - item.initY;
    if (Math.abs(offsetX) > 0 || Math.abs(offsetY) > 0) {
      const rate = offsetX / 10; // 速率等于坐标差除以10,不断缩小运动距离
      const x = item.initX + rate;
      if (Math.abs(rate) < 1) {
        item.initX = item.x; // 当运动距离小于1时,等于实际坐标
      } else {
        if (offsetX > 0) {
          item.initX = x < item.x ? x : item.x;
        } else {
          item.initX = x > item.x ? x : item.x;
        }
      }
      const k = offsetY / offsetX; // 计算斜率
      const y = k * item.initX;
      if (offsetY > 0) {
        item.initY = y < item.y ? y : item.y;
      } else {
        item.initY = y > item.y ? y : item.y;
      }
    } else {
      delete item.initX; // 当运动点坐标和实际坐标相同时,删除初始坐标
      delete item.initY;
    }
  });
  this.drawPoint(); // 绘制粒子函数
  requestAnimationFrame(this.animatDot.bind(this), 1000 / 60);
}

3、点击文字炸开的特效

  • 监听鼠标点击事件,获取鼠标点击坐标clickPointX,clickPointY
  • 设置一个鼠标点击缓冲区clickRange,使一定范围内的粒子都产生炸开的效果;设置一个炸开的最远距离spreadRange,当大于该距离就停止运动
  • y轴的移动还是跟斜率有关系,要计算运动点跟鼠标点击位置的斜率
this.clickRange = 30; // 点击范围
this.spreadRange = 30; // 扩散范围
PBomb() {
  const that = this;
  function animaion(time) {
    that.PBomb();
  }
  if (!this.points.find((item) => item.bomb)) {
    cancelAnimationFrame(animaion); // 停止动画判断
    return;
  }
  const step = 10; // x轴步长,每帧增加或减少的大小
  this.points.forEach((point) => {
    if (point.bomb) {
      if (point.bombX > this.clickPointX) {
        if (point.bombX < point.x + this.spreadRange) {
          point.bombX += step;
        } else {
          point.bomb = false;
        }
      }
      if (point.bombX < this.clickPointX) {
        if (point.bombX > point.x - this.spreadRange) {
          point.bombX -= step;
        } else {
          point.bomb = false;
        }
      }
      const k =
        point.x - this.clickPointX == 0
          ? 1
          : Math.abs(
              (point.y - this.clickPointY) /
                (point.x - this.clickPointX),
            ).toFixed(2); // 计算斜率
      if (point.bombY > this.clickPointY) {
        if (point.bombY < point.y + this.spreadRange) {
          point.bombY += k * step;
        } else {
          point.bomb = false;
        }
      }
      if (point.bombY < this.clickPointY) {
        if (point.bombY > point.y - this.spreadRange) {
          point.bombY -= k * step;
        } else {
          point.bomb = false;
        }
      }
    }
  });
  this.drawPoint();
  setTimeout(() => {
    requestAnimationFrame(animaion);
  }, 1000 / 10);
}

最终效果:

最后加上修改文字内容和大小的功能就完美了

到此这篇关于JavaScript+Canvas实现文字粒子流特效的文章就介绍到这了,更多相关JavaScript Canvas文字粒子流内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript使用canvas实现flappy bird全流程详解

    目录 简介 游戏规则 游戏素材 开始制作 初始化canvas画布 加载资源 背景 地面 管道 笨鸟 碰撞检测 效果 简介 canvas 是HTML5 提供的一种新标签,它可以支持 JavaScript 在上面绘画,控制每一个像素,它经常被用来制作小游戏,接下来我将用它来模仿制作一款叫flappy bird的小游戏.flappy bird(中文名:笨鸟先飞)是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品,于2013年5月24日上线,并在2014年2月突然暴红. 游戏规则 玩家只

  • JavaScript+Canvas模拟实现支付宝画年兔游戏

    目录 动手前的思路 思考1.如何让鼠标只能在特定区域内画画? 思考2.如何让绘制的图画动起来 思考3.如何撤销上一步操作 思考4.如何判断线条绘制完毕 关键步骤 接近过年了,支付宝的集福的活动又开始了,集美们的五福集齐了没有.每年的集福活动都有一些小游戏,今年也不例外,画年画就是其中之一,本篇用canvas来写一个画年兔的游戏. 动手前的思路 画年画游戏规则是:跟着特定轮廓画出线条来. 思考1.如何让鼠标只能在特定区域内画画? 首先要获取到这个轮廓区域所在画布上的位置,判断鼠标绘画的位置是否在指

  • JS+Canvas实现满屏爱心和文字动画的制作

    目录 介绍 步骤 介绍 <canvas> 最早由 Apple 引入 WebKit,用于 Mac OS X 的 Dashboard,随后被各个浏览器实现.如今,所有主流的浏览器都支持它.Canvas API 提供了一个通过 JavaScript 和 HTML 的 <canvas> 元素来绘制图形的方式.它可以用于动画.游戏画面.数据可视化.图片编辑以及实时视频处理等方面.Canvas 适合绘制大数据量图形元素的图表(如热力图.地理坐标系或平行坐标系上的大规模线图或散点图等),也适合实

  • 利用JS+Canvas给南方的冬季来一场纷纷扬扬的大雪

    目录 前言 具体实现 1. 页面布局 2. 雪花的实现 3. 实现下雪 总结 前言 今年冬季都快接近尾声了,身处在南方的我,一点小雪花都还没见到.今年感觉也没以往的冬季冷,以往的冬季就不太能见到一场大雪,今年估计更不可能见到一场大雪纷飞的景色了,因此,用代码来实现一场纷纷扬扬的大雪,完成自己今年看雪的愿望. 具体实现 使用Canvas实现雪花纷飞的场景. 1. 页面布局 页面html,body 设置宽100%.高100vh,铺满整个屏幕,并设置一张好看的背景图或者背景色,能够很好地和白色的雪花相

  • JS技巧Canvas 性能优化脏矩形渲染实例详解

    目录 正文 画布该如何更新? 脏矩形渲染原理 脏矩形渲染实现 性能测试 结尾 正文 使用 Canvas 做图形编辑器时,我们需要自己维护自己的图形树,来保存图形的信息,并定义元素之间的关系. 我们改变画布中的某个图形,去更新画布,最简单的是清空画布,然后根据图形树将所有图形再绘制一遍,这在图形较少的情况下是没什么问题的.但如果图形数量很多,那绘制起来可能就出现卡顿了. 那么,有没有什么办法来优化一下?有,脏矩形渲染. 画布该如何更新? 这里我们假设这么一个场景,画布上绘制了随机位置大量的绿球,然

  • JavaScript利用Canvas实现粒子动画倒计时

    目录 canvas 粒子动画介绍 何为canvas 粒子动画是啥 canvas 定义初始变量 初始化canvas和数字文本 创建一定数量的点 倒计时 倒计时文本绘画 循环绘制 点动画 效果图 canvas 粒子动画介绍 何为canvas canvas是HTML5中新增的一个标签,主要是用于网页实时生成图像并可操作图像,它是用JavaScript操作的bitmap. 粒子动画是啥 粒子动画就是页面上通过发射许多微小粒子来表示不规则模糊物体,比如:用小圆点来模拟下雪.下雨的效果,用模糊线条模拟黑客帝

  • JavaScript+Canvas实现文字粒子流特效

    目录 动手前思考 绘制文字 获取像素点位 渲染粒子 简单的动画效果 1.随机选择四个方向中的某一个方向,生成初始坐标 2.从初始位置运动到实际位置 3.点击文字炸开的特效 动手前思考 首先要在特定的位置生成粒子,要获取到canvas上像素的点位,通过canvas的getImageData函数我们可以得到canvas像素点的信息,获取像素点中透明度大于0的位置. 绘制文字 新建一个canvas画布,在画布上绘制任意的文字 ctx.font = "200px Arial"; ctx.fon

  • JavaScript canvas实现文字时钟

    本文实例为大家分享了canvas实现文字时钟的具体代码,供大家参考,具体内容如下 先看看效果图 代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">

  • 基于JavaScript制作霓虹灯文字 代码 特效

    示例一: 运行效果截图如下: 具体代码如下: http-equiv="Content-Type" content="text/html; charset=gb2312"> 霓虹灯 var Tname="欢迎您的到来!"; var Tlen=Tname.length; document.write(""+Tname+""); var col=new Array("#FFCC00",&

  • JavaScript canvas实现流星特效

    本文实例为大家分享了JavaScript canvas实现流星特效展示的具体代码,供大家参考,具体内容如下 1.控制透明度变化函数 function easeInQuad(curtime,begin,end,duration){ let x = curtime/duration; //x值 let y = x*x; //y值 return begin+(end-begin)*y; //套入最初的公式 } //用平方根构建的缓慢减速运动 核心函数:x*x + 2*x function easeOu

  • JavaScript利用canvas实现鼠标跟随特效

    目录 前言 创建canvas画布 定义鼠标 x / y 初始化canvas 画箭头 循环动画 鼠标事件 前言 canvas是一个很神奇的玩意儿,比如画表格.画海报图都要用canvas去做,前几天有用css去做一个鼠标跟随的恶魔之眼的动画效果,想着能不能用canvas也做一个鼠标跟随的效果呢? 创建canvas画布 canvas画布创建可以直接用canvas标签即可 <canvas></canvas> 也没有过多的样式,基本都是用js去完成画布中的内容的 const canvas =

  • 七个基于JavaScript实现的情人节表白特效

    目录 七夕情人节送花动画告白特效 玫瑰花盛开动画告白特效 3d旋转相册 点击爱心散开动画告白特效 雷电打出告白文字特效 粒子组合告白文字特效 小熊拉手CSS3情人节动画表白特效 七夕情人节送花动画告白特效 效果展示 代码展示: <div id='content'> <ul class='content-wrap'> <!-- 第一副画面 --> <li> <!-- 背景图 --> <div class="a_background&

  • js实现文字闪烁特效的方法

    本文实例讲述了基于jquery实现省市联动特效的代码,分享给大家供大家参考,具体如下: 运行效果图: 实现原理:使用style对象来设置css属性,结合定时器就可以实现js实现文字闪烁特效. 具体代码如下 <html> <head> <meta charset="gb2312" /> <title>js实现文字闪烁特效</title> </head> <script> var flag = 0; fun

  • Javascrip实现文字跳动特效

    一.如何让字符串变成 一个个的字体,让我们去控制 1获取字符串内容 2清空字符串内容 3遍历字符串, 然后一个个的切割出来. 4给切割出来的文字添加定位 5把添加好定位的文字,重新赋值到获取的 元素里面. 二.鼠标滑动上去之后, 该怎么去实现 文字的跳动 1 定义一个变量0 2 定义 定时器 3让变量不断的 减少 4改变元素的top == 变量 5当 变量 达到一定高度的时候,让变量不断的 增加 6 当变量 减少到0(本身位置) 的时候, 7清除动画 改变元素的top = 0(本身位置) <!D

  • JavaScript实现标题栏文字轮播效果代码

    本文实例讲述了JavaScript实现标题栏文字轮播效果代码.分享给大家供大家参考,具体如下: 这里演示的JS文字轮播,显示在标题栏区域,以前个人主页时候经常见到的效果,不过现在都规范了,标题栏一般都不加入这种效果了.但是可以学习一下JS制作实现一些文字特效,运行效果后请查看标题栏. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-title-loop-show-style-demo/ 具体代码如下: <html> <head>

  • 文字模糊特效

    文字模糊特效 var thissize=11 var textfont="Verdana" var textcolor= new Array() textcolor[0]="EEEEEE" textcolor[1]="DDDDDD" textcolor[2]="CCCCCC" textcolor[3]="AAAAAA" textcolor[4]="888888" textcolor[5]

随机推荐