前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >引力粒子特效 - 归为尘埃

引力粒子特效 - 归为尘埃

作者头像
Jimmy_is_jimmy
发布2023-04-22 19:46:26
1K0
发布2023-04-22 19:46:26
举报
文章被收录于专栏:call_me_Rcall_me_R

最近看了《万神殿》,里面的一个效果让我产生创作灵感:

上面人物破碎的效果,一点点脱落

然后,我实现了下面的效果并将其命名为归为尘埃 - 寓意人(或者说万物)在宇宙中的渺小存在:

我们主要使用了 canvas 绘图,下面来一步步讲解:

基本骨架

HTML 里面就两行代码:

代码语言:javascript
复制
<canvas id="canvas"></canvas>
<button id="start">Click to Start</button>

嗯~也许你会有疑问:图片跑哪里去了呢

图片放在了 javascript 文件中处理。

色调指定

在特效中,我们使用的图片是路飞,如下:

图片来源网络,侵删

根据图片的色调,我们指定了 primaryColorsecondColoraccentColor 如下,并对开始按钮样式做了些协调调整:

代码语言:javascript
复制
@primaryColor: #F00; // 主色调
@secondColor: #FDB117; // 次色调
@accentColor: #FDAC77; // 强调色

#start {
  cursor: pointer;
  position: absolute;
  text-align: center;
  top: 60px;
  left: 50%;
  padding: 3px 12px;
  transform: translateX(-50%);
  font-size: 20px;
  font-family: serif;
  border: 1px solid transparent;
  letter-spacing: 2px;
  background: linear-gradient(to bottom right, @primaryColor,@secondColor, @accentColor);
  -webkit-background-clip: text;
  color: transparent;
  border-image: linear-gradient(to top left, @primaryColor, @secondColor, @accentColor) 1;
  &amp;:hover {
    background: linear-gradient(to top left, @primaryColor, @secondColor, @accentColor);
    border-image: linear-gradient(to top left, @accentColor, @secondColor, @primaryColor) 1;
    -webkit-background-clip: text;
    color: transparent;
  }
  text-shadow: 1px 1px 2px #000;
}

关于网站中色调的使用,可以参考我之前的文章 -- 网站设计:十条需避免的常见错误

绘制粒子图像

我们通过 javascript 加载 onload 图片之后,再进行处理:

代码语言:javascript
复制
const imgDom = new Image();
imgDom.src = ''; // 实际代码中,我将图片转换成 base64,当然,你也可以直接使用超链接
// 监听图片加载完后处理
imgDom.onload = function() {
  // some code
}

首先,我们收集图像数据,存放在指定的变量中,如 particleArray 中:

代码语言:javascript
复制
function collectData() {
  particleArray = []; // 这里要重新赋值(清空),避免浏览器窗口更改等造成的粒子记入
  context.drawImage(imgDom, startX, startY); // 绘制图片
  let i = 0;
  for(let y = 0; y < canvasDom.height; y += 1) {
    for(let x = 0; x < canvasDom.width; x += 1) {
      // rgba [i, i + 1, i + 2, i + 3]
      i = (y * canvasDom.width + x) * 4;
      let r = imgData[i];
      let g = imgData[i + 1];
      let b = imgData[i + 2];
      let color = `rgb(${r}, ${g}, ${b})`;
      let a = imgData[i + 3];
      if(a > 0) {
        particleArray.push({
          x,
          y,
          color,
          vx: 0, 
          vy: 0,
          size: size * Math.random()
        })
      }
    }
  }
}

通过上面的函数,我们将图片转换成数组数据,每个粒子数据项包含下面的字段:

代码语言:javascript
复制
{
  x: x, // 坐标点 x
  y: y, // 坐标点 y
  color: color, // 粒子颜色
  vx: 0, // x 轴的加速度
  vy: 0, // y 轴的加速度
  size: size * Math.random(), // 粒子的大小
}

需要留意的是 color 这个字段,生成的粒子数组中,从索引 0 开始,每四个数据为一组,每组里面从前往后依次代表该点的红色、绿色、蓝色和透明度

然后,我们将粒子数据绘制出来:

代码语言:javascript
复制
function drawPaticleImage() {
  for(let i = 0; i < particleArray.length; i += 1) {
    let paticle = particleArray[i];
    context.fillStyle = paticle.color;
    context.fillRect(paticle.x, paticle.y, paticle.size, paticle.size); // 绘制粒子
  }
}

根据上面图像绘制粒子图像,效果如下:

很不错 👍,值得一赞

添加引力效果

下面是整个项目中的重点,也就是添加引力效果。我们设置了触发引力的点:

代码语言:javascript
复制
let gravitySource = {
  x: canvasDom.width / 2, // 引力坐标 x
  y: canvasDom.height / 2, // 引力坐标 y
  strength: 100, // 引力强度
}

接着设置引力函数,对粒子产生相应的影响:

代码语言:javascript
复制
function gravityAttractor(x, y, strength) {
  return function(paticle) {
    let dx = x - paticle.x;
    let dy = y - paticle.y;
    let distance = Math.sqrt(dx * dx + dy * dy);
    let angle = Math.atan2(dy, dx);
    let acceleration = strength / (distance * distance);
    paticle.vx += acceleration * Math.cos(angle);
    paticle.vy += acceleration * Math.sin(angle);
  }
}

获取引力点对粒子的距离 distance,引力点对粒子的角度 angle,当前粒子的加速度 acceleration ,当前粒子在 x 轴方向的加速度和当前粒子在 y 轴方向上的加速度。我们感受下效果:

当然,我们也可以将引力点设置在不同的位置,比如根据鼠标的移动而改变,那会很酷;或者设置多个引力源,那又会是怎么样子的呢?读者可以尝试实现一下。

项目源码见: 归为尘埃

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本骨架
  • 色调指定
  • 绘制粒子图像
  • 添加引力效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档