【Canvas入门】从零开始在Canvas上绘制简单的动画
这篇文章是观看HTML5 Canvas Tutorials for Beginners教程做的记录,所以代码和最后的效果比较相似,教程的内容主要关于这四个部分:
- 创建并设置尺寸
- 添加元素
- 让元素动起来
- 与元素交互
设置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;
到这里,这个简单的项目就结束了,各个颜色的小球会按照随机的速度飘动,鼠标附近的小球会逐渐变大:
相关文章:

【Canvas入门】从零开始在Canvas上绘制简单的动画
这篇文章是观看HTML5 Canvas Tutorials for Beginners教程做的记录,所以代码和最后的效果比较相似,教程的内容主要关于这四个部分: 创建并设置尺寸添加元素让元素动起来与元素交互 设置Canvas的大小 获取到canvas并设置尺寸为当前窗口的大…...
【技术整合】各技术解决方案与对应解决的问题
文章目录 基本实现性能安全 本文将框架分为三大类: 基本实现:包括某个供能或者提供web、移动端、桌面端、或者上述端上的某种功能性能:提升高可用、高并发的框架安全:包括网络安全、权限与容灾等 基本实现 .NET CORE、.NET web基…...

公网远程访问公司内网象过河ERP系统「内网穿透」
文章目录 概述1.查看象过河服务端端口2.内网穿透3. 异地公网连接4. 固定公网地址4.1 保留一个固定TCP地址4.2 配置固定TCP地址 5. 使用固定地址连接 概述 ERP系统对于企业来说重要性不言而喻,不管是财务、生产、销售还是采购,都需要用到ERP系统来协助。…...

Win11的两个实用技巧系列之修改c盘大小方法、功能快捷键大全
Win11 c盘无法更改大小什么原因?Win11修改c盘大小方法 有不少朋友反应Win11 c盘无法更改大小是怎么回事?本文就为大家带来了详细的更改方法,需要的朋友一起看看吧 Win11 c卷无法更改大小什么原因?有用户电脑的系统盘空间太小了,…...

离散数学下--- 代数系统
代数系统 定义: 代数系统是用代数运算构造数学模型的方法。 • 通过构造手段生成,所以也称代数结构 • 代数运算:在集合上建立满足一定规则的运算系统 (一)二元运算 二元运算的定义 二元运算需要满足的两个条件&a…...

java基础入门-04
Java基础入门-04 11、集合&学生管理系统11.1.ArrayList集合和数组的优势对比:11.1.1 ArrayList类概述11.1.2 ArrayList类常用方法11.1.2.1 构造方法11.1.2.2 成员方法11.1.2.3 示例代码 11.1.3 ArrayList存储字符串并遍历11.1.3.1 案例需求11.1.3.2 代码实现 11…...

《面试1v1》java反射
我是 javapub,一名 Markdown 程序员从👨💻,八股文种子选手。 面试官: 你好,请问你对 Java 反射有了解吗? 候选人: 是的,我了解一些。 面试官: 那你能简单…...

【C语言】struct结构体
文章目录 一. 结构体简述二. 结构体的声明和定义1、简单地声明一个结构体和定义结构体变量2、声明结构体的同时也定义结构体变量3、匿名结构体4、配合typedef,声明结构体的同时为结构体取别名5、在声明匿名结构体时,使用typedef给这个匿名结构体取别名 三…...

Docker代码环境打包
1. 介绍 Docker是一种开源的容器化平台,它可以在操作系统级别运行应用程序。通过将应用程序及其依赖项封装成一个可移植的容器,Docker使得应用程序可以在任何环境中轻松部署、运行和管理。使用Docker,开发人员可以避免在不同环境中出现的配置…...
现代CMake高级教程 - 第 6 章:输出与变量
双笙子佯谬老师的【公开课】现代CMake高级教程课程笔记 第 6 章:输出与变量 在运行 cmake -B build 时,打印字符串(用于调试) message("Hello world!")❯ cmake --build buildHello world! -- Configuring done -- G…...

windows/linux文件传输
windows系统下文件传输-FTP python安装pyftpdlib模块 pip install pyftpdlib 这里可能会出现报错,自己看着更换源解决 然后运行python,在2121端口监听 python -m pyftpdlib 然后我们可以使用windows命令行进行操作,自己可以去看下相关文…...
Anoconda安装笔记+win10 更改中文用户名为英文
win10 更改中文用户名为英文 ① WinR打开命令窗口,输入regedit 打开注册表, 手动找到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\ProfileList 在这个目录下面有几个S-1-5-的项,挨个检查每一项, 找到“…...
Java Web应用开发 ——作业七
一.单项选择题(共7题,28.7分) 1 Servlet程序的入口点是( )。 A、 init() B、 main() C、 service() D、 doGet() 正确答案&#…...
echo,date,bc命令详解
文章目录 echo,date,bc命令详解echo(输出文本)date(显示日期的命令)date命令的--date选项date命令 bc(高精度计算器) echo,date,bc命令详解 echo(输出文本) echo命令是一个常用的Shell命令,用于在终端上输出文本。它…...

【Java笔试强训 29】
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一、选择题 二、编程题 🔥求正数数…...
如何在微服务下保证事务的一致性
随着业务的快速发展、业务复杂度越来越高,传统单体应用逐渐暴露出了一些问题,例如开发效率低、可维护性差、架构扩展性差、部署不灵活、健壮性差等等。而微服务架构是将单个服务拆分成一系列小服务,且这些小服务都拥有独立的进程,…...
华为OD机试 - 新学校选址(Python)
题目描述 为了解新学期学生暴涨的问题,小乐村要建立所新学校, 考虑到学生上学安全问题,需要所有学生家到学校的距离最短。 假设学校和所有学生家都走在一条直线之上,请问学校建立在什么位置, 能使得到学校到各个学生家的距离和最短。 输入描述 第一行: 整数 n 取值范围 [1…...

thinkphp6结合layui增删改查综合案列
文章目录 技术栈实现代码实现数据库 本案例适合新手,特别是杠刚入门thinkphp和layui,但又不是特别熟悉这类 主要实现登录退出功能,用户模块的增删改查功能,分页功能是layui表单自带功能 效果图 左侧的菜单栏我没有写对应的页面&am…...
PostgreSQL数据库以任意时间间隔聚合查询group by
文章目录 业务场景以固定时间(年/月/日/时/分/秒)聚合to_char聚合date_trunc聚合 以任意时间聚合date_bin聚合实际应用 业务场景 我们做的是交通信控平台,需要根据实时采集到的交通大数据,计算出一些指标,存储到数据库…...

sql注入(二)盲注,二次注入,宽字节注入
目录 目录 一、布尔盲注 1.判断库名的长度 2.判断数据库名 2.1判断数据库名首字符 2.2 判断数据库名的其余字符 二、时间盲注: 1.判断库名的长度 2.判断库名: 3.判断表名payload: 4.爆出列名 5.爆数据 三、二次注入 1.原理&#…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...