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

HTML鼠标移动的波浪线动画——页面将会初始化一个Canvas元素,并使用JavaScript代码在Canvas上绘制响应鼠标移动的波浪线动画

代码如下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Wave Animation</title><style>body {margin: 0;overflow: hidden;}canvas {display: block;}</style>
</head>
<body><canvas id="canvas"></canvas><script>class Wave {constructor(e) {this.phase = e.phase || 0;this.offset = e.offset || 0;this.frequency = e.frequency || 0.001;this.amplitude = e.amplitude || 1;}update() {this.phase += this.frequency;return this.offset + Math.sin(this.phase) * this.amplitude;}}class Node {constructor() {this.x = 0;this.y = 0;this.vy = 0;this.vx = 0;}}class Line {constructor(e, pos) {this.spring = e.spring + 0.1 * Math.random() - 0.05;this.friction = E.friction + 0.01 * Math.random() - 0.005;this.nodes = [];this.pos = pos; for (let i = 0; i < E.size; i++) {const t = new Node();t.x = this.pos.x;t.y = this.pos.y;this.nodes.push(t);}}update() {let spring = this.spring;let node = this.nodes[0];node.vx += (this.pos.x - node.x) * spring;node.vy += (this.pos.y - node.y) * spring;let prevNode;for (let i = 0; i < this.nodes.length; i++) {node = this.nodes[i];if (i > 0) {prevNode = this.nodes[i - 1];node.vx += (prevNode.x - node.x) * spring;node.vy += (prevNode.y - node.y) * spring;node.vx += prevNode.vx * E.dampening;node.vy += prevNode.vy * E.dampening;}node.vx *= this.friction;node.vy *= this.friction;node.x += node.vx;node.y += node.vy;spring *= E.tension;}}draw(ctx) {let currNode,nextNode,x = this.nodes[0].x,y = this.nodes[0].y;ctx.beginPath();ctx.moveTo(x, y);let i;for (i = 1; i < this.nodes.length - 2; i++) {currNode = this.nodes[i];nextNode = this.nodes[i + 1];x = 0.5 * (currNode.x + nextNode.x);y = 0.5 * (currNode.y + nextNode.y);ctx.quadraticCurveTo(currNode.x, currNode.y, x, y);}currNode = this.nodes[i];nextNode = this.nodes[i + 1];ctx.quadraticCurveTo(currNode.x, currNode.y, nextNode.x, nextNode.y);ctx.stroke();ctx.closePath();}}const E = {friction: 0.5,trails: 20,size: 50,dampening: 0.25,tension: 0.98,};const renderCanvas = function () {const canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");let lines = [];const pos = { x: 0, y: 0 };const wave = new Wave({phase: Math.random() * 2 * Math.PI,amplitude: 85,frequency: 0.0015,offset: 285,});let running = true;let frame = 1;function resizeCanvas() {ctx.canvas.width = window.innerWidth;ctx.canvas.height = window.innerHeight;}resizeCanvas();function animate() {if (running) {ctx.globalCompositeOperation = "source-over";ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);ctx.globalCompositeOperation = "lighter";ctx.strokeStyle = `hsla(${Math.round(wave.update())}, 90%, 50%, 0.25)`;ctx.lineWidth = 1;for (let i = 0; i < E.trails; i++) {const line = lines[i];line.update();line.draw(ctx);}frame++;window.requestAnimationFrame(animate);}}function bindMouseMove(event) {function drawLine() {lines = [];for (let i = 0; i < E.trails; i++)lines.push(new Line({ spring: 0.45 + (i / E.trails) * 0.025 }, pos));}function move(e) {e.touches? ((pos.x = e.touches[0].pageX), (pos.y = e.touches[0].pageY)): ((pos.x = e.clientX), (pos.y = e.clientY));e.preventDefault();}function start(e) {if (e.touches.length === 1) {pos.x = e.touches[0].pageX;pos.y = e.touches[0].pageY;}}document.removeEventListener("mousemove", bindMouseMove);document.removeEventListener("touchstart", bindMouseMove);document.addEventListener("mousemove", move);document.addEventListener("touchmove", move);document.addEventListener("touchstart", start);move(event);drawLine();animate();}document.addEventListener("mousemove", bindMouseMove);document.addEventListener("touchstart", bindMouseMove);document.body.addEventListener("orientationchange", resizeCanvas);window.addEventListener("resize", resizeCanvas);window.addEventListener("focus", () => {if (!running) {running = true;animate();}});window.addEventListener("blur", () => {running = true;});};renderCanvas();</script>
</body>
</html>

#解析HTML代码

  1. HTML结构
    • 页面中包含一个<canvas>元素,用于绘制动画。
    • CSS样式用于隐藏页面的默认边距,并使画布全屏显示。
  2. JavaScript代码
    • 包含了之前定义的所有类和函数。
    • renderCanvas函数被调用以启动动画。
  3. 事件监听
    • 添加了鼠标移动和触摸事件监听器,以更新线条的位置。
    • 窗口调整大小事件监听器用于保持画布与窗口大小同步。

将上述HTML代码保存为一个.html文件,并在浏览器中打开,你就可以看到一个随着鼠标移动变化的波浪线动画了。

#解析JS代码

  1. Wave 类
    • 用于描述一个正弦波,包含相位(phase)、偏移(offset)、频率(frequency)和振幅(amplitude)属性。
    • update 方法用于更新波形,每次调用时相位增加一定的频率,并返回当前波形的位置。
  2. Node 类
    • 代表动画中的一个点,拥有位置(x, y)和速度(vx, vy)。
  3. Line 类
    • 描述由多个Node组成的线段。
    • 包含弹簧系数(spring)、摩擦系数(friction)和节点列表(nodes)。
    • update 方法用于更新每个节点的位置,根据相邻节点的位置和速度以及弹簧和摩擦力。
    • draw 方法用于在Canvas上下文上绘制线条。
  4. E 对象
    • 定义了动画的一些常量,如摩擦系数、轨迹数量、节点数量、阻尼系数和张力系数。
  5. renderCanvas 函数
    • 初始化Canvas,并设置其尺寸。
    • 创建一个Wave实例,并定义了一些动画相关的变量。
    • animate 函数负责动画的绘制和更新。
    • 通过监听鼠标移动和触摸事件来更新线条的位置,并开始动画循环。

相关文章:

HTML鼠标移动的波浪线动画——页面将会初始化一个Canvas元素,并使用JavaScript代码在Canvas上绘制响应鼠标移动的波浪线动画

代码如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Wave Animation</title><style&…...

树莓派开发相关知识八-其他传感器

1、蜂鸣器 #!/usr/bin/env python #coding:utf-8import RPi.GPIO as GPIO import time OUT5 def init():GPIO.setwarnings(False)GPIO.setmode(GPIO.BCM)GPIO.setup(OUT,GPIO.OUT)#蜂鸣器鸣叫函数 def beep(seconds):GPIO.output(OUT,GPIO.HIGH)time.sleep(seconds)GPIO.output…...

ComfyUI - ComfyUI 工作流中集成 SAM2 + GroundingDINO 处理图像与视频 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/143359538 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 SAM2 与…...

STM32G4 双ADC模式之常规同步模式独立注入模式

目录 概述 1 认识双ADC模式 2 功能实现 2.1 原理介绍 2.2 实现方法 概述 本文主要介绍STM32G4 双ADC模式之常规同步模式&独立注入模式相关内容&#xff0c;包括ADC模块的功能介绍&#xff0c;实现框架结构&#xff0c;以及常规同步模式&独立注入模式ADC的转换的实…...

深入理解网络协议:OSPF、VLAN、NAT与ACL详解

OSPF工作过程与基础配置 一、OSPF的工作过程 OSPF&#xff08;开放最短路径优先&#xff09;是一个广泛使用的路由协议&#xff0c;它的工作过程可以总结为以下几个步骤&#xff1a; 启动与邻居发现 OSPF在配置完成后&#xff0c;会通过本地组播地址224.0.0.5发送HELLO包。HE…...

idea 配置tomcat 服务

选择tomcat的安装路径 选到bin的文件夹的上一层就行...

.net core 接口,动态接收各类型请求的参数

[HttpPost] public async Task<IActionResult> testpost([FromForm] object info) { //Postman工具测试结果&#xff1a; //FromBody,Postman的body只有rawjson时才进的来 //参数为空时&#xff0c;Body(form-data、x-www-form-urlencoded)解析到的数据也有所…...

关注!这些型号SSD有Windows蓝屏问题需要修复

近期&#xff0c;在闪迪官方有一个SSD FW升级提醒&#xff0c;主要是为了解决Windows 11 24H2系统蓝屏的问题&#xff1a; Fix问题&#xff1a;这些SSD的主机内存缓冲区&#xff08;Host Memory Buffer&#xff0c;简称HMB&#xff09;功能可能会导致系统出现蓝屏死机&#xff…...

go语言gin框架平滑关闭——思悟项目技术2

目录 前言 直接关闭的缺陷 平滑关闭的使用场景 例子 思悟项目&#xff1a; golang qq邮件发送验证码——思悟项目技术1 前言 平滑关闭&#xff08;graceful shutdown&#xff09;是指在停止服务时&#xff0c;能够让现有的连接、任务或者操作优雅地完成&#xff0c;而不是…...

K8S flannel网络模式对比

K8S flannel网络模式对比 VXLAN 模式Host-GW 模式如何查看 Flannel 的网络模式?如何修改 Flannel 的网络模式?如何修改flannel vxlan端口?Flannel 是一个 Kubernetes 中常用的网络插件,用于在集群中的节点之间提供网络连接。Flannel 提供了多种后端实现方式,vxlan 和 host…...

Vue前端框架:Vue前端项目文件目录

文章目录 package.json 文件node_modulessrc&#xff08;Source Code 的缩写&#xff09;文件夹主要子文件夹及内容 publicdist package.json 文件 所在文件夹&#xff08;通常是项目根目录&#xff09; 虽然 package.json 本身不是一个文件夹&#xff0c;但它所在的文件夹&a…...

git回滚到指定的提交

如果你想回滚到特定的提交&#xff08;例如 aa0ca72c&#xff09;&#xff0c;并且丢弃之后的所有更改&#xff0c;可以使用 git reset 命令。请注意&#xff0c;git reset 会改变你的提交历史&#xff0c;所以在多人协作项目中应谨慎使用。如果已经推送到远程仓库&#xff0c;…...

手机怎么玩森林之子?远程玩森林之子教程

你喜欢《森林之子》这款开放世界恐怖生存模拟游戏吗&#xff1f;玩家会被派到一座孤岛上&#xff0c;寻找一位失踪的亿万富翁&#xff0c;并深陷被食人生物占领的地方。你需要制作工具和武器、建造房屋&#xff0c;倾尽全力生存下去&#xff0c;无论独自一人还是与朋友一起。如…...

深度学习之网络与计算

1 网络操作与计算 1.1 前向传播与反向传播&#xff1f; 神经网络的计算主要有两种&#xff1a;前向传播&#xff08;foward propagation, FP&#xff09;作用于每一层的输入&#xff0c;通过逐层计算得到输出结果&#xff1b;反向传播&#xff08;backward propagation, BP&a…...

《JVM第1课》Java 跨平台原理

无痛快速学习JVM&#xff0c;欢迎订阅本免费专栏 JVM Java的特性就是程序员一次编写&#xff0c;到处运行&#xff0c;意思是我们只需要写一份代码&#xff0c;就可以在不同的操作系统&#xff08;windows、Linux、Mac OS等&#xff09;中运行。但是不同的操作系统能看懂的指令…...

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-30

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-30 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-30目录1. Step Guided Reasoning: Improving Mathematical Reasoning using Guidance Generation and Step Reasoning摘要研究背…...

加强版 第五节图像处理与视频分析

基本概念 图像轮廓 主要针对二值图像&#xff0c;轮廓是一系列点 vector<vector<Point>xxx用于存储多个点 vector<Vec4i>xxx包含四个整数&#xff0c;分别代表下一个轮廓的索引&#xff0c;上一个轮廓的索引&#xff0c;一个子轮廓的索引和父轮廓的索引 相…...

Orleans8.2入门测试

微软官方文档&#xff1a;快速入门&#xff1a;使用 ASP.NET Core 生成第一个 Orleans 应用 - .NET | Microsoft Learn 项目及引入的nuget库&#xff1a; 1、接口项目&#xff1b;2、接口实现项目&#xff1b;3、silo项目&#xff1b;4、客户端项目 其中Microsoft.Orleans.St…...

【Linux 25】网络套接字 socket 概念

文章目录 &#x1f308; 一、IP 地址概念⭐ 1. IP 地址的作用⭐ 2. 源 IP 地址和目的 IP 地址 &#x1f308; 二、端口号概念⭐ 1. 源端口号和目的端口号⭐ 2. 端口号范围划分⭐ 3. 端口号 VS 进程 ID⭐ 4. 套接字 socket 的概念 &#x1f308; 三、传输层的典型代表协议⭐ 1. …...

python openai 通过Function Call 创建自动化任务

目录 一、什么是Function Call(函数掉用) 1. 功能概述 2. 工作原理 二、如何实现函数调用 1、定义自己的get_weather 函数 2、给助手添加函数调用 3、写好instrction,指导assistant去掉用你定义的方法。 4、最后也是最重要的,捕获 Assistant 的 Function Call 三、…...

AWS WebRTC:获取ICE服务地址(part 2): ICE Agent的作用

上一篇&#xff0c;已经获取到了ICE服务地址&#xff0c;从返回结果中看&#xff0c;是两组TURN服务地址。 拿到这些地址有什么用呢&#xff1f;接下来就要说到WebRTC中ICE Agent的作用了&#xff0c;返回的服务地址会传给WebRTC最终给到ICE Agent。 ICE Agent的作用&#xf…...

OpenCV中的分水岭算法 (C/C++)

OpenCV中的分水岭算法 (C/C) &#x1f3de;️ 分水岭算法 (Watershed Algorithm) 是一种在图像处理和计算机视觉中广泛应用的图像分割方法。它特别适用于分离图像中相互接触或重叠的对象。其基本思想是将灰度图像看作一个地形景观&#xff0c;其中灰度值代表海拔高度。算法模拟…...

Ansys Zemax | 手机镜头设计 - 第 2 部分:光机械封装

本文该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;涵盖了从概念、设计到制造和结构变形的分析。本文是四部分系列的第二部分&#xff0c;介绍了在 Ansys Speos 环境中编辑光学元件以及在整合机械组件后分析系统。案例研究对象是一家全球运营制造商的智能手机镜头系统…...

华为云Flexus+DeepSeek征文 | 基于Dify和DeepSeek-R1开发企业级AI Agent全流程指南

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 1. 前言 2. 环境准备 2.1 华为云资源准备 2.1 实…...

解决 Go 中 `loadinternal: cannot find runtime/cgo` 错误

在 Go 开发中&#xff0c;loadinternal: cannot find runtime/cgo 是一个相对不常见但可能令人困惑的错误。这个错误通常与 CGO 的使用和配置有关。本文将探讨这个错误的成因&#xff0c;并提供解决方案&#xff0c;帮助你在未来的开发中避免类似问题。 错误背景 在 Go 项目中…...

AWS EC2 实例告警的创建与删除

在AWS云环境中&#xff0c;监控EC2实例的运行状态至关重要。通过CloudWatch告警&#xff0c;用户可以实时感知实例的CPU、网络、磁盘等关键指标异常。本文将详细介绍如何通过AWS控制台创建EC2实例告警&#xff0c;以及如何安全删除不再需要的告警规则&#xff0c;并附操作截图与…...

PostgreSQL如何更新和删除表数据

这节说下怎样更新和删除表数据&#xff0c;当然认识命令了&#xff0c;可以问AI帮忙写。 接上节先看下天气表weather的数据&#xff0c;增加了杭州和西安的数据&#xff1a; 一.UPDATE更新命令 用UPDATE命令更新现有的行。 假设所有 杭州 5月12日的温度低了两度&#xff0c;用…...

如何科学测量系统的最高QPS?

要准确测量系统的最高QPS&#xff08;Queries Per Second&#xff09;&#xff0c;既不能简单依赖固定请求数&#xff08;如2万次&#xff09;&#xff0c;也不能盲目压到服务器崩溃。以下是专业的方法论和步骤&#xff1a; 1. 核心原则 目标&#xff1a;找到系统在稳定运行&a…...

el-table-column如何获取行数据的值

在Element UI的el-table组件中&#xff0c;你可以通过el-table-column的slot-scope属性&#xff08;在Vue 2.x中&#xff09;或者#default插槽的scope属性&#xff08;在Vue 3.x中&#xff09;来获取当前行的数据。以下是如何实现这一功能的详细步骤&#xff1a; ‌在el-table-…...

基于Piecewise Jerk Speed Optimizer的速度规划算法(附ROS C++/Python仿真)

目录 1 时空解耦运动规划2 PJSO速度规划原理2.1 优化变量2.2 代价函数2.3 约束条件2.4 二次规划形式 3 算法仿真3.1 ROS C仿真3.2 Python仿真 1 时空解耦运动规划 在自主移动系统的运动规划体系中&#xff0c;时空解耦的递进式架构因其高效性与工程可实现性被广泛采用。这一架…...