当前位置: 首页 > news >正文

【Canvas入门】从零开始在Canvas上绘制简单的动画

这篇文章是观看HTML5 Canvas Tutorials for Beginners教程做的记录,所以代码和最后的效果比较相似,教程的内容主要关于这四个部分:

  1. 创建并设置尺寸
  2. 添加元素
  3. 让元素动起来
  4. 与元素交互

设置Canvas的大小

获取到canvas并设置尺寸为当前窗口的大小:

var canvas = document.getElementById(canvas_id);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

获取到二维的Context并赋值给变量c,后面对canvas的操作主要都是通过c进行的:

var c = canvas.getContext("2d")

填充矩形

在(x,y)坐标处,填充一个宽为width,高为height的矩形:

c.fillRect(x, y, width, height)

设定填充矩形的颜色:

c.fillStyle = "green";         // 填充的颜色为绿色
c.fillRect(100, 100, 100, 100) // 在(100,100)坐标处填充一个边长为100的正方形

绘制线段

c.beginPath();               // 开始绘制路径
c.moveTo(100, 200);          // 相当于笔尖在空中移动到(x,y)坐标的位置,也就是
c.lineTo(200, 300);          // 让笔尖从之前的坐标到现在的坐标(200,300)画一条线段
c.strokeStyle = "#4455ff";   // 设置线条的颜色
c.stroke();                  // 渲染到Canvas上

绘制圆形

,以(x,y)为圆心,radius为半径画圆,startAngle, endAngle分别为起点角度和终点角度(弧度制),最后一个参数是可选的counterclockwise,true为逆时针,false顺时针,默认为false:

arc(x, y, radius, startAngle, endAngle)
arc(x, y, radius, startAngle, endAngle, counterclockwise)

在 (100, 100) 处画一个半径为30,顺时针的圆:

c.beginPath();
c.arc(100, 100, 30, 0, 2 * Math.PI, false);
c.strokeStyle = "#00ff00";
c.stroke();

使用for循环生成随机位置的圆形

Math.random() 生成0-1之间的随机数,所以要乘上宽度和高度来让它的随机范围扩大到整个屏幕,也就是得到了很多个随机的坐标。

for (var i = 0; i < 100; i++) {var x = Math.random() * window.innerWidth;var y = Math.random() * window.innerHeight;var r = Math.random() * 100;                // 半径也随机生成,范围在0-100c.beginPath();c.arc(x, y, r, 0, 2 * Math.PI);c.strokeStyle = "#0fff00";c.stroke();
}

这样就生成了100个位置随机,大小随机的圆形。

加入动画

定义一个函数 animate() 并在内部调用,这样就得到了一个一直重复运行的函数,可以在这个函数里面更新元素的状态。
设置初始坐标为 (200, 200),x方向的速度 v x v_x vx为2,y方向的速度 v y v_y vy为0,在每一次刷新的时候使用速度来更新位置。
我们知道匀速运动时 x = v t x=vt x=vt,所以可以通过速度改变位移。还可以通过加速度 a a a来改变速度 v v v,在Canvas中实现变速运动。

var x = 200, y = 200;
var vx = 2, vy = 0;
function animate() {requestAnimationFrame(animate);c.clearRect(0, 0, window.innerWidth, window.innerHeight); // 清除掉前一帧绘制的内容,否则会不断的重叠c.beginPath();c.arc(x, y, 30, 0, 2 * Math.PI);c.stroke();x += vx;y += vy;
}
animate();

更多会动的圆

定义一个类,用来画一个圆心在 (200, 200) 处,半径为30的圆:

class Circle{constructor(x, y) { // 在 constructor 中完成一些值的初始化this.x = x;this.y = y;}draw() {c.beginPath();c.arc(this.x, this.y, 30, 0, 2 * Math.PI); c.stroke();}
}
var circle = new Circle(200, 200);
// 当调用 new Circle(200, 200); 时,会将类的参数列表传入constructor()的参数列表,并执行constructor()
circle.draw()

接下来把更新 (x, y) 坐标的部分写成Circle类的update()函数,并把 draw() 方法也包含进来:

class Circle{constructor(x, y, vx, vy, radius) {this.x = x;this.y = y;this.vx = vx;this.vy = vy;this.radius = radius;}draw() { // 根据 x,y 坐标,半径 radius 画一个圆c.beginPath();c.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);c.stroke();}update() { // 更新 x,y 坐标, 将越界时反弹, 更新后绘制圆形if (this.x - this.radius < 0 || this.x + this.radius > window.innerWidth)  this.vx = -this.vx;if (this.y - this.radius < 0 || this.y + this.radius > window.innerHeight) this.vy = -this.vy;this.x += this.vx;this.y += this.vy;this.draw();}}var circle = new Circle(200, 200, 2, 2, 30);function animate() {requestAnimationFrame(animate);c.clearRect(0, 0, window.innerWidth, window.innerHeight);circle.update(); // 这边只需要一次次的调用 update() 即可}

有了Circle类,就可以方便的创建很多个Circle对象,并更新它们的位置。

var circleArray = [];
for (var i = 0; i < 50; i++) {var x = Math.random() * window.innerWidth;var y = Math.random() * window.innerHeight;var vx = (Math.random() - 0.5) * 3;var vy = (Math.random() - 0.5) * 3;var radius = Math.random() * 100;circleArray.push(new Circle(x, y, vx, vy, radius))
}function animate() {requestAnimationFrame(animate);c.clearRect(0, 0, WIDTH, HEIGHT);for (var i = 0; i < circleArray.length; i++) {circleArray[i].update();}
}
animate();

与鼠标交互

给移动的小球增加与鼠标交互的动画,当鼠标靠近时增大小球的半径,当鼠标远离时,再让它缩小,需要监听mousemove事件,并更新mouse.x和mouse.y的值:

window.addEventListener('mousemove', function (event) {mouse.x = event.clientX;mouse.y = event.clientY;
})

然后在update()里面:

if (Math.sqrt((this.x - mouse.x) ** 2 + (this.y - mouse.y) ** 2) < 100) {if (this.radius < maxRadius)this.radius += 1;} else if (this.radius > minRadius) {this.radius -= 1;}

为了方便使用,可以提前设定好最小半径和最大半径:

const maxRadius = 40, minRadius = 2;

适配不同尺寸的屏幕

当窗口大小发生变化时,会触发resize事件,可以通过监听这个事件,来重新初始化Canvas中的小球。

window.addEventListener('resize', function (event) {init();
})

如果小球的数量是固定的,那么较小的屏幕上会太密集,而较大的屏幕上看起来又会太稀疏,所以可以根据屏幕的大小来设置小球的个数,我这里的做法是将窗口的面积除以5000并向下取整来计算出小球的个数:

var circleArray = [];
function init() {canvas.width = window.innerWidth;canvas.height = window.innerHeight;var ballNumber = Math.floor((window.innerWidth * window.innerHeight) / 5000);circleArray = [];for (var i = 0; i < ballNumber; i++) {var x = Math.random() * window.innerWidth;var y = Math.random() * window.innerHeight;var vx = (Math.random() - 0.5) * 3;var vy = (Math.random() - 0.5) * 3;var radius = Math.random() * minRadius + 1;//Math.random() * 20;circleArray.push(new Circle(x, y, vx, vy, radius))}
}

为了让小球更好看一些,可以为它们填充不同的颜色:

const colorArray = ["#AFD3E2", "#F2B6A0", "#FC4F00", "#FFEEB3", "#A5C0DD", "#FF6969", "#ECC9EE", "#00FFCA"];

constructor() 中设置当前这个小球的填充颜色:

this.color = colorArray[Math.floor(Math.random() * colorArray.length)]

在填充之前设定一下颜色:

c.fillStyle = this.color;

到这里,这个简单的项目就结束了,各个颜色的小球会按照随机的速度飘动,鼠标附近的小球会逐渐变大:
请添加图片描述

http://www.lryc.cn/news/64233.html

相关文章:

  • 【技术整合】各技术解决方案与对应解决的问题
  • 公网远程访问公司内网象过河ERP系统「内网穿透」
  • Win11的两个实用技巧系列之修改c盘大小方法、功能快捷键大全
  • 离散数学下--- 代数系统
  • java基础入门-04
  • 《面试1v1》java反射
  • 【C语言】struct结构体
  • Docker代码环境打包
  • 现代CMake高级教程 - 第 6 章:输出与变量
  • windows/linux文件传输
  • Anoconda安装笔记+win10 更改中文用户名为英文
  • Java Web应用开发 ——作业七
  • echo,date,bc命令详解
  • 【Java笔试强训 29】
  • 如何在微服务下保证事务的一致性
  • 华为OD机试 - 新学校选址(Python)
  • thinkphp6结合layui增删改查综合案列
  • PostgreSQL数据库以任意时间间隔聚合查询group by
  • sql注入(二)盲注,二次注入,宽字节注入
  • Linux 基础操作
  • 2.4 等比数列
  • 2022年新能源汽车专题讲座
  • Git操作远程仓库
  • 制造策略 ETO、MTO、ATO、MTS
  • Git(六):基本命令(3):储藏、标签、拉取、子模块
  • 7.0、Java继承与多态 - 多态的特性
  • 将系统从机械硬盘迁移至固态硬盘上
  • 《Netty》从零开始学netty源码(五十一)之PoolArena的内存释放与扩容
  • Android Input系统事件分发分析
  • Linux-基本指令2