canvas动画:黑客帝国

Over in Part 2 of this series we created a ball that would ricochet around the screen and change color when it collided with a border. Now we’re going to use what we learned to make this rain animation that dynamically renders drops with particle effect as each drop hits the bottom of our canvas.

在本系列的第2部分中 ,我们创建了一个球,该球会在屏幕周围跳动并在与边框碰撞时改变颜色。 现在,我们将使用我们学到的知识制作这个雨动画 ,当每个液滴击中画布的底部时, 该动画将动态渲染具有粒子效果的液滴。

样板 (Boilerplate)

Since we’re going to be working so close to the bottom of the screen we should hide any horizontal scroll bars with overflow: hidden, and we’ll darken it a bit so be a bit less eye burning.

由于我们要在屏幕底部附近工作,因此我们应该隐藏所有带有overflow: hidden水平滚动条overflow: hidden ,然后将其变暗一些,以免造成眼睛灼伤。

index.html
index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta http-equiv="X-UA-Compatible" content="ie=edge"/><title>HTML Canvas</title><style>body {overflow: hidden;background-color: #1a202c;}</style></head><body><canvas></canvas></body><script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script><script src="./canvas.js"></script>
</html>
canvas.js
canvas.js
// Utilities
const randomNum = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
const randomColor = colors => colors[Math.floor(Math.random() * colors.length)];// Get canvas element
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');// Make canvas fullscreen
canvas.width = innerWidth;
canvas.height = innerHeight;
addEventListener('resize', () => {canvas.width = innerWidth;canvas.height = innerHeight;
});// Control Panel
const gui = new dat.GUI();const controls = {count: 0,velocity: 0,
};gui.add(controls, 'dx', 0, 10);
gui.add(controls, 'dy', 0, 10);// New Object
class Ball {constructor(x, y, radius, color) {this.x = x;this.y = y;this.radius = radius;this.color = color;}
};Ball.prototype.draw = function () {c.beginPath();c.fillStyle = this.color;c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);c.fill();c.closePath();
};Ball.prototype.update = function () {this.x += controls.dx;this.y += -controls.dy;this.draw();
};const ball = new Ball(innerWidth / 2, innerHeight / 2, 50, 'red');// Handle changes
const animate = () => {requestAnimationFrame(animate);c.clearRect(0, 0, canvas.width, canvas.height);ball.update();
};animate();

下降 (Drop)

Let’s start by getting our main drops working. We just need to store all of the variables for each drop as an object, draw a line on the screen, and add some value to the y position whenever update is ran to make it move downward.

让我们开始让我们的主要drops开始工作。 我们只需要将每个放置的所有变量存储为一个对象,在屏幕上画一条线,并在每次运行update使其向下移动时在y位置添加一些值即可。

canvas.js
canvas.js
class Drop {constructor(x, y, dy, thickness, length, color) {this.x = x;this.y = y;this.dy = dy;this.thickness = thickness;this.length = length;this.color = color;}
};Drop.prototype.draw = function () {c.beginPath();c.strokeStyle = this.color;c.lineWidth = this.thickness;c.moveTo(this.x, this.y);c.lineTo(this.x, this.y - this.length);c.stroke();c.closePath();
}Drop.prototype.update = function () {this.y += this.dy;this.draw();
}

Let’s render one onto the center of the canvas screen to see if it’s working.

让我们在画布屏幕的中央渲染一个,看看它是否在工作。

const drop = new Drop(innerWidth / 2, innerHeight / 2, 2, 5, 30, 'red');const animate = () => {requestAnimationFrame(animate);c.clearRect(0, 0, canvas.width, canvas.height);drop.update();
};animate();

股票代号 (Ticker)

That’s nice, but we’re going to need a lot more rendering along the top. To have multiple drops we could just make an array, use a for loop to assign random values to each item before pushing them to the array, and use forEach to update each of them per frame. But just using a for loop would only render the drops once, which would all move past our canvas out of site. So we have to be a bit creative to continually add new drops while removing all drops that move below our screen.

很好,但是沿着顶部我们将需要更多渲染。 要获得多个drop,我们可以制作一个数组,使用for循环为每个项目分配随机值,然后再将它们推入数组,并使用forEach每帧更新每个项目。 但是,仅使用for循环只会渲染一次拖放,所有这些都会从画布移出站点。 因此,我们必须具有一定的创造力,以便在删除屏幕下方移动的所有液滴的同时不断添加新的液滴。

To do this, we’re going to make a ticker that will count up by one every frame, every time it’s perfectly divisible by some number we’ll add a new drop to the array. Whatever number we divide it by will control how often new drops are rendered. To remove them, and save on processing power, we’ll just splice them out of the array when they’re past the bottom.

为此,我们将制作一个行情自动收录器,每帧将其完全除以某个数字,便会在该帧中加一新滴。 无论我们用多少除以它,都将控制渲染新液滴的频率。 为了删除它们并节省处理能力,我们将在它们超过底部时将它们拼接出阵列。

Using the modulo operator (%) we can divide a number and check if the remainder equals 0. So the higher it is the less often new drops will be rendered.

使用取模运算符( % ),我们可以除以一个数,然后检查余数是否等于0。因此,它越高,呈现新液滴的频率就越低。

While we’re here let’s give them some color. I find that using different values of the same color, along with random thickness and length, helps to give the illusion of some depth. I recommend checking out Kuler for your color palettes.

当我们在这里时,让我们给他们一些颜色。 我发现使用相同颜色的不同值以及随机的厚度和长度有助于给出某种深度的错觉。 我建议您查看Kuler的调色板。

canvas.js
canvas.js
const colors = [ '#9C4AFF', '#8C43E6', '#7638C2', '#5E2C99', '#492378'];let drops = [];
let ticker = 0;
const animate = () => {requestAnimationFrame(animate);// Try using the 'residue' effect from Part 2// c.fillStyle = 'rgba(33, 33, 33, .3)'; //Lower opacity creates a longer tail// c.fillRect(0, 0, canvas.width, canvas.height);c.clearRect(0, 0, canvas.width, canvas.height);drops.forEach((drop, index) => {drop.update();if (drop.y >= canvas.height) drops.splice(index, 1);});// Timing between dropsticker++;let count = controls.count === 0 ? 0 : randomNum(controls.count + 5, controls.count);if (ticker % count == 0) {const x = randomNum(0, innerWidth);const y = 0;const dy = controls.velocity === 0 ? 0 : randomNum(controls.velocity, controls.velocity + 10);const thickness = randomNum(3, 5);const length = randomNum(20, 50);drops.push(new Drop(x, y, dy, thickness, length, randomColor(colors)));};
};

水滴和重力 (Droplets and Gravity)

To create our splash effect as they hit the ground we’re going to need some smaller particles that will have a gravity-like effect, arcing out from the main drop. Our Droplet class is going to be pretty similar to our main Drop, with a few differences since the droplets will be circles instead of lines.

为了在飞溅到地面时产生飞溅效果,我们需要一些较小的粒子,这些粒子具有类似重力的作用,并从主液滴中飞出。 我们的Droplet类将与我们的主Drop类非常相似,但有所不同,因为液滴将是圆形而不是直线。

canvas.js
canvas.js
class Droplet {constructor(x, y, dx, dy, radius, color) {this.x = x;this.y = y;this.dx = dx;this.dy = dy;this.radius = radius;this.color = color;this.gravity = .1;}
};Droplet.prototype.draw = function () {c.beginPath();c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);c.fillStyle = this.color;c.fill();c.closePath();
};

The main thing we want to worry about is our gravity. Gravity causes our downward movement to increase, so we’ll want to add this to our dy on the update method. So when we generate many droplets moving up, with a negative dy value, and add our gravity value onto it every frame it will slow down, reverse direction, and speed up until it is removed past our canvas. I made a simpler example with just the droplets, you can experiment with here.

我们要担心的主要事情是重力。 重力作用使我们向下运动增加,因此我们需要把它添加到我们的dyupdate方法。 因此,当我们生成许多带有负dy值的液滴向上移动并在其上添加重力值时,它会减速,反向并加快速度,直到将其移出画布为止。 我仅用液滴做了一个简单的示例,您可以在此处进行试验。

Droplet.prototype.update = function () {this.dy += this.gravity;this.y += this.dy;this.x += this.dx;this.draw();
};

And we’ll update and remove them just like our main drops.

我们将像我们的主要drop一样更新和删除它们。

let droplets = [];
const animate = () => {droplets.forEach((droplet, index) => {droplet.update();if (droplet.y >= canvas.height) droplets.splice(index, 1);});
};

溅 (Splash)

Adding our particles is actually very simple, we can just use a for loop to generate them with the main drops position and pass-in some random values for the rest. Let’s also add some gravity to our drops to make them fall a bit more realistically.

添加我们的粒子实际上非常简单,我们可以使用for循环使用主液滴位置生成它们,并为其余粒子传入一些随机值。 让我们在水滴上增加一些重力,使其更真实地下落。

canvas.js
canvas.js
class Drop {constructor(x, y, dy, thickness, length, color) {this.x = x;this.y = y;this.dy = dy;this.thickness = thickness;this.color = color;this.length = length;this.gravity = .4;}
};Drop.prototype.update = function () {// Stops drops if velocity controller is set to 0if (this.dy > 0) this.dy += this.gravity;this.y += this.dy;// It runs splash over the whole length of the drop, to we'll narrow it down to the end.if (this.y > canvas.height - 100) this.splash(this.x, this.y + (this.length * 2));this.draw();
}Drop.prototype.splash = function (x, y) {for (let i = 0; i < 5; i++) {const dx = randomNum(-3, 3);const dy = randomNum(-1, -5);const radius = randomNum(1, 3);droplets.push(new Droplet(x, y, dx, dy, radius, randomColor(colors)));};
};

结论 (Conclusion)

While there’s still an enormous amount he learn about HTML canvas, hopefully this short series was a gentle enough introduction to its possibilities. Most sites are similar in a lot of ways but the ability to create custom animations offers a uniqueness that the most popular automated site builder tools never will.

尽管他对HTML画布了解很多,但希望这个简短的系列对它的可能性有足够的介绍。 大多数站点在很多方面都是相似的,但是创建自定义动画的能力提供了一种独特性,而大多数流行的自动化站点构建器工具却从未如此。

翻译自: https://www.digitalocean.com/community/tutorials/js-canvas-animations-gravity

canvas动画:黑客帝国

canvas动画:黑客帝国_使用Canvas API进行动画处理-第3部分:重力和动态渲染相关推荐

  1. canvas动画科技园_使用 canvas 实现精灵动画

    在最近项目中需要实现一个精灵动画,素材方只提供了一个短视频素材,所以在实现精灵动画之前先介绍两个工具来帮助我们更好的实现需求.在这篇文章中,主要是介绍两个命令行工具来实现将一个短视频文件转化成一张 s ...

  2. canvas动画科技园_构建canvas动画框架(一)

    最近一直在做canvas动画效果,发现canvas这个东西做动画不是不可以.相对于flash,它太底层.如果有给力的编辑器或者给力的框架的话,它就能发挥出更大的威力. 于是决定自己写一个简单一点的动画 ...

  3. svg动画制作_制作第一个SVG动画

    svg动画制作 Story of a designer trying to code animations instead of asking a dev to figure it out. 一位设计 ...

  4. java运用ascii实现动画效果_安卓开发20:动画之Animation 详细使用-主要通过java代码实现动画效果...

    AlphaAnimation 透明效果实现: activity_main.xml中仅仅是一个简单的图片,下面的例子都会使用这个xml: xmlns:tools="http://schemas ...

  5. canvas 边界模糊_解决canvas画图模糊的问题

    canvas 画图经常发现他是模糊的.解决这个问题主要从两个方面下手. 改变canvas渲染的像素 情况:画1像素的线条看起来模糊不清,好像更宽的样子. 解决方案 var ctx = canvas.g ...

  6. 怎么用canvas画秒针_用canvas画一个钟表

    body{ background: #000000; } #c1{ background: #FFFFFF; } span{color: #FFFFFF;} var oC=document.getEl ...

  7. 与虫子尾交3d动画网站_不容错过的三维动画设计展!快来pick吧!

    3D是英文"3 Dimensions"的简称,中文是指三维.三个维度.三个坐标,即有长.宽.高. 在设计方面来讲,3D多被我们应用在动画.影视制作等设计制作方面.随着科技的发展,大 ...

  8. php imagegif 动画,使用PHP的ImageMagick API制作动画GIF

    虽然我不是PHP专家,但我知道这个问题并不太难.你想要做的是创建一个可以附加帧的Imagick对象.对于每个帧,您可以更改定时等参数. 假设您正在使用从基本Web表单上传的图像,我编写了一个基本示例, ...

  9. Java风车动画代码_用CSS3实现风车动画效果

    Document body{ background: purple; } *{ margin: 0; padding: 0; } ul{ position: relative; width: 100p ...

最新文章

  1. pythonapi是什么_python接口自动化(一)--什么是接口、接口优势、类型(详解)...
  2. 【Android 基础】Animation 动画介绍和实现
  3. 云计算技术 — 混合云
  4. C语言读写配置文件--转载
  5. 数组排序方法及C实现的总结
  6. 安装oracle sqldeveloper
  7. 7.3.8.1 - 并发多线程 死锁和递归锁 - 信号量
  8. 阿里CEO张勇:建立良好的消费环境是阿里20年来努力工作的方向
  9. web前端好学吗?如何能提高CSS编写技巧 提高Web前端开发效率
  10. 苹果Mac时间日程管理工具:Things 备注支持 Markdown
  11. 最简单DIY基于STM32F407探索者开发板的MPU6050陀螺仪姿态控制舵机程序
  12. php laravel mvc模式,laravel框架之MVC设计
  13. java 异或代码编程
  14. Typora保留文本格式
  15. SEO项目管理,该问自己的几个问题?
  16. 【机器学习】花卉识别01
  17. 磁碟机变种简单分析(lsass.exe、smss.exe、dnsq.dll、NetApi000.sys)
  18. Percona监控数据库解决方案
  19. 阿里执行副主席蔡崇信投资NBA篮网队;工信部约谈运营商,不得限制用户资费选择丨价值早报
  20. H3C SE 教程笔记——构建安全优化的广域网(下)

热门文章

  1. 交换机的背板容量、交换容量和包转发能力
  2. HTNL5列表,表格,音频,视频,iframe内联框架
  3. leet code: Two Sum
  4. 数据库 实验六 存储过程
  5. 语言模型Katz backoff以及HMM模型
  6. 几十年前的老旧照片如何修复?还不知道旧照片怎么恢复清晰吗?
  7. 怎么从扫描的PDF文档/图片里提取文字
  8. Go语言学习十二 变量和常量
  9. 【计算机组成原理】冯诺伊曼结构和计算机性能指标
  10. shell中let 命令与Expr命令介绍