Movatterモバイル変換


[0]ホーム

URL:


  1. 面向开发者的 Web 技术
  2. Web API
  3. Canvas API
  4. Canvas 教程
  5. 高级动画

此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

View in EnglishAlways switch to English

高级动画

在上一章,我们制作了基本动画以及逐步了解了让物件移动的方法。在这一部分,我们将会对运动有更深的了解并学会添加一些符合物理的运动以让我们的动画更加高级。

绘制小球

我们将会画一个小球用于动画学习,所以首先在画布上画一个球。下面的代码帮助我们建立画布。

html
<canvas width="600" height="300"></canvas>

跟平常一样,我们需要先画一个 context(画布场景)。为了画出这个球,我们又会创建一个包含一些相关属性以及draw() 函数的ball 对象,来完成绘制。

js
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var ball = {  x: 100,  y: 100,  radius: 25,  color: "blue",  draw: function () {    ctx.beginPath();    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);    ctx.closePath();    ctx.fillStyle = this.color;    ctx.fill();  },};ball.draw();

这里并没有什么特别的。小球实际上是一个简单的圆形,在arc() 函数的帮助下画出。

添加速率

现在我们有了一个小球,正准备添加一些基本动画,正如我们上一章所学的。又是这样,window.requestAnimationFrame() 再一次帮助我们控制动画。小球依旧依靠添加速率矢量进行移动。在每一帧里面,我们依旧用clear 清理掉之前帧里旧的圆形。

js
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var ball = {  x: 100,  y: 100,  vx: 5,  vy: 2,  radius: 25,  color: "blue",  draw: function () {    ctx.beginPath();    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);    ctx.closePath();    ctx.fillStyle = this.color;    ctx.fill();  },};function draw() {  ctx.clearRect(0, 0, canvas.width, canvas.height);  ball.draw();  ball.x += ball.vx;  ball.y += ball.vy;  raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", function (e) {  raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", function (e) {  window.cancelAnimationFrame(raf);});ball.draw();

边界

若没有任何的碰撞检测,我们的小球很快就会超出画布。我们需要检查小球的 x 和 y 位置是否已经超出画布的尺寸以及是否需要将速度矢量反转。为了这么做,我们把下面的检查代码添加进draw 函数:

js
if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {  ball.vy = -ball.vy;}if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {  ball.vx = -ball.vx;}

首个示例

让我们看看现今它变得如何。

HTML

html
<canvas width="600" height="300"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");let raf;const ball = {  x: 100,  y: 100,  vx: 5,  vy: 2,  radius: 25,  color: "blue",  draw() {    ctx.beginPath();    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);    ctx.closePath();    ctx.fillStyle = this.color;    ctx.fill();  },};function draw() {  ctx.clearRect(0, 0, canvas.width, canvas.height);  ball.draw();  ball.x += ball.vx;  ball.y += ball.vy;  if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {    ball.vy = -ball.vy;  }  if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {    ball.vx = -ball.vx;  }  raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", (e) => {  raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", (e) => {  window.cancelAnimationFrame(raf);});ball.draw();

结果

移动你的鼠标到画布里开启动画。

加速度

为了让动作更真实,你可以像这样处理速度,例如:

js
ball.vy *= 0.99;ball.vy += 0.25;

这会逐帧减少垂直方向的速度,所以小球最终将只会在地板上弹跳。

第二个示例

HTML

html
<canvas width="600" height="300"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");let raf;const ball = {  x: 100,  y: 100,  vx: 5,  vy: 2,  radius: 25,  color: "blue",  draw() {    ctx.beginPath();    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);    ctx.closePath();    ctx.fillStyle = this.color;    ctx.fill();  },};function draw() {  ctx.clearRect(0, 0, canvas.width, canvas.height);  ball.draw();  ball.x += ball.vx;  ball.y += ball.vy;  ball.vy *= 0.99;  ball.vy += 0.25;  if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {    ball.vy = -ball.vy;  }  if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {    ball.vx = -ball.vx;  }  raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", (e) => {  raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", (e) => {  window.cancelAnimationFrame(raf);});ball.draw();

结果

长尾效果

现在,我们使用的是clearRect 函数帮我们清除前一帧动画。若用一个半透明的fillRect 函数取代之,就可轻松制作长尾效果。

js
ctx.fillStyle = "rgba(255,255,255,0.3)";ctx.fillRect(0, 0, canvas.width, canvas.height);

第三个示例

HTML

html
<canvas width="600" height="300"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");let raf;const ball = {  x: 100,  y: 100,  vx: 5,  vy: 2,  radius: 25,  color: "blue",  draw() {    ctx.beginPath();    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);    ctx.closePath();    ctx.fillStyle = this.color;    ctx.fill();  },};function draw() {  ctx.fillStyle = "rgba(255, 255, 255, 0.3)";  ctx.fillRect(0, 0, canvas.width, canvas.height);  ball.draw();  ball.x += ball.vx;  ball.y += ball.vy;  ball.vy *= 0.99;  ball.vy += 0.25;  if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {    ball.vy = -ball.vy;  }  if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {    ball.vx = -ball.vx;  }  raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", (e) => {  raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", (e) => {  window.cancelAnimationFrame(raf);});ball.draw();

结果

添加鼠标控制

为了更好地控制小球,我们可以用mousemove事件让它跟随鼠标活动。下面例子中,click 事件会释放小球然后让它重新跳起。

<canvas width="600" height="300"></canvas>
js
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var running = false;var ball = {  x: 100,  y: 100,  vx: 5,  vy: 1,  radius: 25,  color: "blue",  draw: function () {    ctx.beginPath();    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);    ctx.closePath();    ctx.fillStyle = this.color;    ctx.fill();  },};function clear() {  ctx.fillStyle = "rgba(255,255,255,0.3)";  ctx.fillRect(0, 0, canvas.width, canvas.height);}function draw() {  clear();  ball.draw();  ball.x += ball.vx;  ball.y += ball.vy;  if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {    ball.vy = -ball.vy;  }  if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {    ball.vx = -ball.vx;  }  raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mousemove", function (e) {  if (!running) {    clear();    ball.x = e.offsetX;    ball.y = e.offsetY;    ball.draw();  }});canvas.addEventListener("click", function (e) {  if (!running) {    raf = window.requestAnimationFrame(draw);    running = true;  }});canvas.addEventListener("mouseout", function (e) {  window.cancelAnimationFrame(raf);  running = false;});ball.draw();

用你的鼠标移动小球,点击可以释放。

Breakout

本短文仅仅解释了一小部分的创建高级动画的技巧。其实还有更多!试试添加一个球拍,一些砖块,然后将这个例子弄成一个Breakout(译者注:打砖块游戏)如何?查看我们的游戏开发区去查阅更多相关文章。

参考

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp