博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
canvas动画:黑客帝国_使用Canvas API进行动画处理-第3部分:重力和动态渲染
阅读量:2505 次
发布时间:2019-05-11

本文共 9156 字,大约阅读时间需要 30 分钟。

canvas动画:黑客帝国

Over in 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 that dynamically renders drops with particle effect as each drop hits the bottom of our canvas.

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

样板 (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
      
HTML Canvas
canvas.js
canvas.js
// Utilitiesconst randomNum = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);const randomColor = colors => colors[Math.floor(Math.random() * colors.length)];// Get canvas elementconst canvas = document.querySelector('canvas');const c = canvas.getContext('2d');// Make canvas fullscreencanvas.width = innerWidth;canvas.height = innerHeight;addEventListener('resize', () => {  canvas.width = innerWidth;  canvas.height = innerHeight;});// Control Panelconst gui = new dat.GUI();const controls = {  count: 0,  velocity: 0,};gui.add(controls, 'dx', 0, 10);gui.add(controls, 'dy', 0, 10);// New Objectclass 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 changesconst 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 for your color palettes.

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

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 drops  ticker++;  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 .

我们要担心的主要事情是重力。 重力作用使我们向下运动增加,因此我们需要把它添加到我们的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 0  if (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画布了解很多,但希望这个简短的系列对它的可能性有足够的介绍。 大多数站点在很多方面都是相似的,但是创建自定义动画的能力提供了一种独特性,而大多数流行的自动化站点构建器工具却从未如此。

翻译自:

canvas动画:黑客帝国

转载地址:http://dihgb.baihongyu.com/

你可能感兴趣的文章
ASP.NET MVC ajax提交 防止CSRF攻击
查看>>
关于CSS伪类选择器
查看>>
适用于带文字 和图片的垂直居中方法
查看>>
Part 2 - Fundamentals(4-10)
查看>>
使用Postmark测试后端存储性能
查看>>
NSTextView 文字链接的定制化
查看>>
第五天站立会议内容
查看>>
CentOs7安装rabbitmq
查看>>
(转))iOS App上架AppStore 会遇到的坑
查看>>
解决vmware与主机无法连通的问题
查看>>
做好产品
查看>>
项目管理经验
查看>>
笔记:Hadoop权威指南 第8章 MapReduce 的特性
查看>>
JMeter响应数据出现乱码的处理-三种解决方式
查看>>
获取设备实际宽度
查看>>
图的算法专题——最短路径
查看>>
SQL批量删除与批量插入
查看>>
Notes on <High Performance MySQL> -- Ch3: Schema Optimization and Indexing
查看>>
C语言之一般树
查看>>
懂了很多大道理,却依旧过不好一生
查看>>