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

使用 HTML5 Canvas 实现动态蜈蚣动画

使用 HTML5 Canvas 实现动态蜈蚣动画

在这里插入图片描述

1. 项目概述

我们将通过 HTML 和 JavaScript 创建一个动态蜈蚣。蜈蚣由多个节段组成,每个节段看起来像一个小圆形,并且每个节段上都附带有“脚”。蜈蚣的头部会在画布上随机移动。
完整代码在底部!!!!!!!!!!!!

2. 项目实现步骤
2.1 设置 HTML 和 Canvas

首先,我们需要设置一个基本的 HTML 页面,并在页面中插入一个 <canvas> 元素。这是我们绘制动画的区域。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>动态蜈蚣动画</title><style>body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f0f0; }canvas { border: 1px solid #000; }</style>
</head>
<body><canvas id="myCanvas" width="800" height="400"></canvas><script src="script.js"></script>
</body>
</html>

在上面的代码中,我们定义了一个宽度为 800px,高度为 400px 的 canvas,并通过 script.js 文件来处理动画逻辑。

2.2 初始化蜈蚣的结构

蜈蚣的构成非常简单:它由多个节段组成,每个节段是一个小圆形。每个节段都有一个位置和角度,我们通过数组来保存每个节段的信息。在初始化时,蜈蚣的头部位于画布的中间,并且节段按顺序排列。

let segments = [];  // 存储每个节段的位置
const bodySegments = 20;    // 蜈蚣的节数
const segmentRadius = 10;   // 每个节段的半径
const segmentSpacing = 25;  // 节段之间的间距// 初始化蜈蚣位置
function initMillipede() {for (let i = 0; i < bodySegments; i++) {segments.push({x: 100 + i * (segmentRadius * 2 + segmentSpacing), // 确保每个节段有间距y: canvas.height / 2,  // 初始化位置在画布中间angle: 0,  // 每个节段的初始角度});}
}
3. 绘制蜈蚣

蜈蚣的绘制分为多个部分:每个节段、头部、脚和尾巴。我们使用 canvas 的绘图 API 来绘制每个节段。每个节段是一个圆形,头部稍大,脚则是由短线条组成的。

function drawMillipede() {ctx.clearRect(0, 0, canvas.width, canvas.height);  // 清除画布内容// 绘制蜈蚣的每一节for (let i = 0; i < segments.length; i++) {const segment = segments[i];ctx.save();ctx.translate(segment.x, segment.y);ctx.rotate(segment.angle);ctx.beginPath();ctx.arc(0, 0, segmentRadius, 0, Math.PI * 2);ctx.fillStyle = i % 2 === 0 ? "green" : "darkgreen"; // 交替颜色ctx.fill();ctx.restore();}// 绘制蜈蚣的头部(红色)ctx.save();ctx.translate(segments[0].x, segments[0].y);ctx.rotate(segments[0].angle);ctx.beginPath();ctx.arc(0, 0, segmentRadius * 1.5, 0, Math.PI * 2);ctx.fillStyle = "red"; // 蜈蚣头部的颜色ctx.fill();ctx.restore();
}
4. 蜈蚣的随机运动

蜈蚣的运动采用了随机的速度和方向。我们通过调整蜈蚣头部的速度(speedXspeedY)来实现蜈蚣在画布上随机移动。同时,我们对速度的变化进行了限制,以防蜈蚣的移动过快。

let speedX = 2;  // 蜈蚣头部水平方向的速度
let speedY = 2;  // 蜈蚣头部垂直方向的速度
let maxSpeed = 4; // 最大速度function updateMillipede() {segments[0].x += speedX;segments[0].y += speedY;// 更新节段的位置和角度,逐步跟随前一个节段for (let i = segments.length - 1; i > 0; i--) {segments[i].x = segments[i - 1].x;segments[i].y = segments[i - 1].y;segments[i].angle = segments[i - 1].angle;}// 随机改变蜈蚣的运动速度,产生不规则的运动speedX += (Math.random() - 0.5) * 0.5;speedY += (Math.random() - 0.5) * 0.5;// 限制速度的范围speedX = Math.max(-maxSpeed, Math.min(maxSpeed, speedX));speedY = Math.max(-maxSpeed, Math.min(maxSpeed, speedY));// 如果蜈蚣头部超出画布的边界,则反弹if (segments[0].x > canvas.width || segments[0].x < 0) {speedX = -speedX;  // 反转水平方向的速度}if (segments[0].y > canvas.height || segments[0].y < 0) {speedY = -speedY;  // 反转垂直方向的速度}
}
5. 动画循环

为了实现持续的动画,我们使用 requestAnimationFrame 来创建一个动画循环。每一帧,我们更新蜈蚣的位置并重新绘制它。

function animate() {updateMillipede();  // 更新蜈蚣的位置和角度drawMillipede();    // 绘制蜈蚣requestAnimationFrame(animate);  // 请求下一帧
}initMillipede();  // 初始化蜈蚣
animate();        // 启动动画循环
6. 完整代码

将上述代码整合,完整的实现如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>生动的蜈蚣动画</title><style>body {margin: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: black;}canvas {border: 1px solid white;}</style></head><body><canvas id="myCanvas" width="800" height="400"></canvas><script>// 获取 canvas 元素和上下文const canvas = document.getElementById('myCanvas');const ctx = canvas.getContext('2d');// 蜈蚣的参数const segmentRadius = 10; // 每个节段的半径const segmentSpacing = 1; // 节段之间的间距const bodySegments = 80; // 蜈蚣的节数const footLength = 15; // 脚的长度const footSpacing = 5; // 脚的间距let segments = []; // 存储每个节段的位置let angle = 0; // 角度,用于让蜈蚣做弯曲运动let speed = 5; // 蜈蚣移动的速度// 初始化蜈蚣位置function initMillipede() {for (let i = 0; i < bodySegments; i++) {segments.push({x: 100 + i * (segmentRadius + segmentSpacing),y: canvas.height / 2,angle: 0 // 每个节段的初始角度});}}// 绘制蜈蚣function drawMillipede() {// 清除之前的画布内容ctx.clearRect(0, 0, canvas.width, canvas.height);// 绘制蜈蚣的每一节for (let i = 1; i < segments.length; i++) {const segment = segments[i];ctx.save();ctx.translate(segment.x, segment.y);ctx.rotate(segment.angle);ctx.beginPath();ctx.arc(0, 0, segmentRadius, 0, Math.PI * 2);ctx.fillStyle = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`; // 交替颜色ctx.fill();// 绘制脚drawFeet(segment, i);ctx.restore();}// 绘制蜈蚣的头部(红色)ctx.save();ctx.translate(segments[0].x, segments[0].y);ctx.rotate(segments[0].angle);ctx.beginPath();ctx.arc(0, 0, segmentRadius * 1.5, 0, Math.PI * 2);ctx.fillStyle = 'yellow'; // 蜈蚣头部的颜色ctx.fill();// 绘制头部触须drawAntennae(segments[0]);ctx.restore();// 绘制蜈蚣的尾巴drawTail(segments[segments.length - 1]);}// 绘制蜈蚣的脚function drawFeet(segment, index) {const footOffset = index % 2 === 0 ? -footSpacing : footSpacing;for (let i = 0; i < 2; i++) {// 每节有两只脚const angleOffset = i === 0 ? -Math.PI / 4 : Math.PI / 4; // 左右两只脚ctx.save();ctx.translate(0, 0);ctx.rotate(segment.angle + angleOffset);// 绘制脚ctx.beginPath();ctx.moveTo(0, segmentRadius);ctx.lineTo(footLength, segmentRadius + footOffset);ctx.lineWidth = 2;ctx.strokeStyle = 'white';ctx.stroke();ctx.restore();}}// 绘制头部的触须function drawAntennae(segment) {const antennaLength = 20;ctx.save();ctx.translate(0, 0);ctx.rotate(segment.angle);ctx.beginPath();ctx.moveTo(0, -segmentRadius * 1.5);ctx.lineTo(antennaLength, -segmentRadius * 1.5 - 10);ctx.moveTo(0, -segmentRadius * 1.5);ctx.lineTo(antennaLength, -segmentRadius * 1.5 + 10);ctx.lineWidth = 2;ctx.strokeStyle = 'white';ctx.stroke();ctx.restore();}// 绘制蜈蚣的尾巴function drawTail(segment) {const tailLength = 20;const tailAngle = Math.PI / 4; // 向下的角度ctx.save();ctx.translate(segment.x, segment.y);ctx.rotate(segment.angle + Math.PI);ctx.beginPath();ctx.moveTo(0, segmentRadius);ctx.lineTo(tailLength, segmentRadius + tailLength);ctx.lineWidth = 2;ctx.strokeStyle = 'green';ctx.stroke();ctx.restore();}// 更新蜈蚣的位置和角度function updateMillipede() {// 头部的运动轨迹:向右偏移segments[0].x += speed;segments[0].y += Math.sin(angle) * 3; // 头部上下波动// 更新节段的位置和角度,逐步跟随前一个节段for (let i = segments.length - 1; i > 0; i--) {segments[i].x = segments[i - 1].x;segments[i].y = segments[i - 1].y;segments[i].angle = segments[i - 1].angle;}// 更新头部的角度,给蜈蚣的运动加入弯曲感segments[0].angle += Math.sin(angle) * 0.1; // 使蜈蚣头部产生摇摆的效果// 改变角度来产生蜈蚣的弯曲运动angle += 0.1;// 如果蜈蚣头部超出画布的右边界,则回到左边if (segments[0].x > canvas.width) {segments[0].x = -segmentRadius * 2;}}// 动画循环function animate() {updateMillipede(); // 更新蜈蚣的位置和角度drawMillipede(); // 绘制蜈蚣requestAnimationFrame(animate); // 请求下一帧}// 初始化并开始动画initMillipede();animate();</script></body>
</html>
7. 结尾

拜拜,彦祖,亦菲们

相关文章:

使用 HTML5 Canvas 实现动态蜈蚣动画

使用 HTML5 Canvas 实现动态蜈蚣动画 1. 项目概述 我们将通过 HTML 和 JavaScript 创建一个动态蜈蚣。蜈蚣由多个节段组成&#xff0c;每个节段看起来像一个小圆形&#xff0c;并且每个节段上都附带有“脚”。蜈蚣的头部会在画布上随机移动。 完整代码在底部&#xff01;&…...

计算机视觉目标检测——DETR(End-to-End Object Detection with Transformers)

计算机视觉目标检测——DETR(End-to-End Object Detection with Transformers) 文章目录 计算机视觉目标检测——DETR(End-to-End Object Detection with Transformers)摘要Abstract一、DETR算法1. 摘要&#xff08;Abstract&#xff09;2. 引言&#xff08;Introduction&#…...

uniapp .gitignore

打开HBuilderX&#xff0c;在项目根目录下新建文件 .gitignore复制下面内容 #忽略unpackge目录下除了res目录的所有目录 unpackage/* !unpackage/res/#忽略.hbuilderx目录 .hbuilderx# 忽略node_modules目录下的所有文件 node_modules/# 忽略锁文件 package-lock.json yarn.l…...

JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化

目录 1. 背景2. 实现2.1 pom.xml2.2 FruitController.java2.3 DispatcherServlet.java2.4 applicationContext.xml 3. 测试 1. 背景 前面我们做了Servlet的一个案例。但是存在很多问题&#xff0c;现在我们要做优化&#xff0c;优化的步骤如下&#xff1a; 每个Fruit请求都需…...

备忘一个FDBatchMove数据转存的问题

使用FDBatchMove的SQL导入excel表到sql表&#xff0c;设置条件时一头雾水&#xff0c;函数不遵守sql的规则。 比如替换字段的TAB键值为空&#xff0c;replace(字段名,char(9),)竟然提示错误&#xff0c;百思不得其解。 试遍了几乎所有的函数&#xff0c;竟然是chr(9)。 这个…...

CEF127 编译指南 MacOS 篇 - 编译 CEF(六)

1. 引言 经过前面的准备工作&#xff0c;我们已经完成了所有必要的环境配置。本文将详细介绍如何在 macOS 系统上编译 CEF127。通过正确的编译命令和参数配置&#xff0c;我们将完成 CEF 的构建工作&#xff0c;最终生成可用的二进制文件。 2. 编译前准备 2.1 确认环境变量 …...

【更新】LLM Interview

课程链接&#xff1a;BV1o217YeELo 文章目录 LLM基础相关1. LLMs概述2. 大语言模型尺寸3. LLMs的优势与劣势4. 常见的大模型分类5. 目前主流的LLMs开源模型体系有哪些&#xff08;Prefix Decoder&#xff0c;Causal Decoder&#xff0c;Encoder-Decoder的区别是什么&#xff09…...

Django 视图中使用 Redis 缓存优化查询性能

在 Web 应用程序开发中,查询数据库是一个常见的操作,但如果查询过于频繁或耗时,就会影响应用程序的性能。为了解决这个问题,我们可以使用缓存技术,将查询结果暂时存储在内存中,从而减少对数据库的访问。本文将介绍如何在 Django 视图中使用 Redis 缓存来优化查询性能。 © …...

正则表达式解析与功能说明

正则表达式解析与功能说明 表达式说明 String regex "\\#\\{TOASRTRINNG\\((.*?)((.*?))\\)(\\})";该正则表达式的作用是匹配形如 #{TOASRTRINNG(...)} 的字符串格式。以下是正则表达式的详细解析&#xff1a; 拆解与解析 1. \\# 匹配&#xff1a;# 字符。说明…...

STUN服务器实现NAT穿透

NAT穿透的问题 在现代网络环境中&#xff0c;大多数设备都位于NAT(网络地址转换)设备后面。这给点对点(P2P)通信带来了挑战&#xff0c;因为NAT会阻止外部网络直接访问内部设备。STUN(Session Traversal Utilities for NAT)服务器就是为了解决这个问题而设计的。 STUN是什么?…...

音视频入门基础:MPEG2-TS专题(19)——FFmpeg源码中,解析TS流中的PES流的实现

一、引言 FFmpeg源码在解析完PMT表后&#xff0c;会得到该节目包含的视频和音频信息&#xff0c;从而找到音视频流。TS流的音视频流包含在PES流中。FFmpeg源码通过调用函数指针tss->u.pes_filter.pes_cb指向的回调函数解析PES流的PES packet&#xff1a; /* handle one TS…...

tomcat的安装以及配置(基于linuxOS)

目录 安装jdk环境 yum安装 验证JDK环境 安装tomcat应用 yum安装 ​编辑 使用yum工具进行安装 配置tomcat应用 关闭防火墙和selinux 查看端口开启情况 ​编辑 访问tomcat服务 安装扩展包 重启服务 查看服务 源码安装 进入tomcat官网进行下载 查找自己要用的to…...

因子分解(递归)

1.素分解式(简单版) 任务描述 编写函数&#xff0c;输出一个正整数的素数分解式。主函数的功能为输入若干正整数&#xff08;大于1&#xff09;&#xff0c;输出每一个数的素分解式。素数分解式是指将整数写成若干素数(从小到大)乘积的形式。例如&#xff1a; 202*2*5 362*2*…...

【Python】pandas库---数据分析

大学毕业那年&#xff0c;你成了社会底层群众里&#xff0c;受教育程度最高的一批人。 前言 这是我自己学习Python的第四篇博客总结。后期我会继续把Python学习笔记开源至博客上。 上一期笔记有关Python的NumPy数据分析&#xff0c;没看过的同学可以去看看&#xff1a;【Pyt…...

RabbitMQ 的7种工作模式

RabbitMQ 共提供了7种⼯作模式,进⾏消息传递,. 官⽅⽂档:RabbitMQ Tutorials | RabbitMQ 1.Simple(简单模式) P:⽣产者,也就是要发送消息的程序 C:消费者,消息的接收者 Queue:消息队列,图中⻩⾊背景部分.类似⼀个邮箱,可以缓存消息;⽣产者向其中投递消息,消费者从其中取出消息…...

负载均衡式在线OJ

文章目录 项目介绍所用技术与开发环境所用技术开发环境 项目框架compiler_server模块compiler编译功能comm/util.hpp 编译时的临时文件comm/log.hpp 日志comm/util.hpp 时间戳comm/util.hpp 检查文件是否存在compile_server/compiler.hpp 编译功能总体编写 runner运行功能资源设…...

【3D打印机】启庞KP3S热床加热失败报错err6

最近天冷&#xff0c;打印机预热突然失败&#xff0c;热床无法加热&#xff0c;过了一段时间报错err6&#xff0c;查看另一篇资料说是天气冷原因&#xff0c;导致代码的PID控温部分达不到预期加热效果&#xff0c;从而自检报错&#xff0c;然后资料通过修改3D打印机代码的方式进…...

基于 MATLAB 的图像增强技术分享

一、引言 图像增强是数字图像处理中的重要环节&#xff0c;其目的在于改善图像的视觉效果&#xff0c;使图像更清晰、细节更丰富、对比度更高&#xff0c;以便于后续的分析、识别与理解等任务。MATLAB 作为一款功能强大的科学计算软件&#xff0c;提供了丰富的图像处理工具和函…...

前端知识补充—HTML

1. HTML 1.1 什么是HTML HTML(Hyper Text Markup Language), 超⽂本标记语⾔ 超⽂本: ⽐⽂本要强⼤. 通过链接和交互式⽅式来组织和呈现信息的⽂本形式. 不仅仅有⽂本, 还可能包含图⽚, ⾳频, 或者⾃已经审阅过它的学者所加的评注、补充或脚注等等 标记语⾔: 由标签构成的语⾔…...

安卓从Excel文件导入数据到SQLite数据库的实现

在现代的移动应用开发中&#xff0c;数据的处理和管理是至关重要的一环。有时候&#xff0c;我们需要从外部文件&#xff08;如Excel文件&#xff09;中导入数据&#xff0c;以便在应用程序中使用。本文将介绍如何在Android应用中使用Java代码从一个Excel文件中导入数据到SQLit…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...