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

Canvas动画实战:从入门到精通

Canvas动画实战从入门到精通前言各位前端小伙伴不知道你们有没有想过在浏览器中实现复杂的动画效果Canvas可以让你实现各种炫酷的动画我曾经开发过一个在线绘图应用使用Canvas实现了流畅的画笔效果和动画回放功能用户体验非常棒Canvas动画概述Canvas是HTML5提供的一个2D绘图API可以用于创建动态图形、游戏、数据可视化等。Canvas动画的核心是使用requestAnimationFrame进行帧同步。Canvas基础创建Canvas元素canvas idmyCanvas width800 height600/canvas获取上下文const canvas document.getElementById(myCanvas) const ctx canvas.getContext(2d)基本绘图操作// 绘制矩形 ctx.fillStyle red ctx.fillRect(10, 10, 100, 100) // 绘制圆形 ctx.beginPath() ctx.arc(200, 200, 50, 0, Math.PI * 2) ctx.fillStyle blue ctx.fill() // 绘制路径 ctx.beginPath() ctx.moveTo(300, 100) ctx.lineTo(400, 200) ctx.lineTo(300, 300) ctx.closePath() ctx.strokeStyle green ctx.lineWidth 3 ctx.stroke()Canvas动画基础使用requestAnimationFramefunction animate() { ctx.clearRect(0, 0, canvas.width, canvas.height) update() render() requestAnimationFrame(animate) } animate()带时间戳的动画let lastTime 0 function animate(timestamp) { const deltaTime timestamp - lastTime lastTime timestamp ctx.clearRect(0, 0, canvas.width, canvas.height) update(deltaTime) render() requestAnimationFrame(animate) } requestAnimationFrame(animate)Canvas动画实战粒子系统class Particle { constructor(x, y) { this.x x this.y y this.vx (Math.random() - 0.5) * 4 this.vy (Math.random() - 0.5) * 4 this.radius Math.random() * 5 2 this.color hsl(${Math.random() * 360}, 70%, 50%) } update() { this.x this.vx this.y this.vy if (this.x 0 || this.x canvas.width) { this.vx * -1 } if (this.y 0 || this.y canvas.height) { this.vy * -1 } } render() { ctx.beginPath() ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2) ctx.fillStyle this.color ctx.fill() } } const particles [] for (let i 0; i 100; i) { particles.push(new Particle( Math.random() * canvas.width, Math.random() * canvas.height )) } function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height) particles.forEach(particle { particle.update() particle.render() }) requestAnimationFrame(animate) } animate()物理模拟class Ball { constructor(x, y, radius) { this.x x this.y y this.radius radius this.vx 0 this.vy 0 this.gravity 0.5 this.bounce 0.8 } update() { this.vy this.gravity this.x this.vx this.y this.vy if (this.y this.radius canvas.height) { this.y canvas.height - this.radius this.vy * -this.bounce } if (this.x - this.radius 0) { this.x this.radius this.vx * -1 } if (this.x this.radius canvas.width) { this.x canvas.width - this.radius this.vx * -1 } } render() { ctx.beginPath() ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2) ctx.fillStyle orange ctx.fill() ctx.strokeStyle black ctx.lineWidth 2 ctx.stroke() } } const ball new Ball(400, 100, 30) ball.vx 5 function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height) ball.update() ball.render() requestAnimationFrame(animate) } animate()Canvas高级技术使用ImageDatafunction createImageData() { const imageData ctx.createImageData(canvas.width, canvas.height) const data imageData.data for (let i 0; i data.length; i 4) { data[i] Math.random() * 255 // R data[i 1] Math.random() * 255 // G data[i 2] Math.random() * 255 // B data[i 3] 255 // A } ctx.putImageData(imageData, 0, 0) }使用离屏Canvasconst offscreenCanvas document.createElement(canvas) offscreenCanvas.width canvas.width offscreenCanvas.height canvas.height const offscreenCtx offscreenCanvas.getContext(2d) function renderToOffscreen() { offscreenCtx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height) offscreenCtx.fillStyle red offscreenCtx.fillRect(10, 10, 100, 100) ctx.drawImage(offscreenCanvas, 0, 0) }使用Canvas合成模式ctx.globalCompositeOperation source-over // 默认 ctx.globalCompositeOperation multiply // 正片叠底 ctx.globalCompositeOperation screen // 滤色 ctx.globalCompositeOperation overlay // 叠加 ctx.globalCompositeOperation lighter // 变亮 ctx.globalCompositeOperation darken // 变暗 ctx.globalCompositeOperation xor // 异或Canvas性能优化批量绘制function renderObjects(objects) { ctx.save() objects.forEach(obj { ctx.translate(obj.x, obj.y) ctx.rotate(obj.rotation) ctx.fillStyle obj.color ctx.fillRect(-obj.width/2, -obj.height/2, obj.width, obj.height) ctx.setTransform(1, 0, 0, 1, 0, 0) }) ctx.restore() }使用缓存const cacheCanvas document.createElement(canvas) cacheCanvas.width 100 cacheCanvas.height 100 const cacheCtx cacheCanvas.getContext(2d) function drawCachedObject() { cacheCtx.fillStyle blue cacheCtx.fillRect(0, 0, 100, 100) ctx.drawImage(cacheCanvas, 0, 0) }使用requestAnimationFrame节流const TARGET_FPS 30 const FRAME_INTERVAL 1000 / TARGET_FPS let lastFrameTime 0 function animate(timestamp) { if (timestamp - lastFrameTime FRAME_INTERVAL) { requestAnimationFrame(animate) return } lastFrameTime timestamp ctx.clearRect(0, 0, canvas.width, canvas.height) update() render() requestAnimationFrame(animate) } requestAnimationFrame(animate)Canvas动画库使用Konva.jsimport Konva from konva const stage new Konva.Stage({ container: container, width: 800, height: 600 }) const layer new Konva.Layer() stage.add(layer) const circle new Konva.Circle({ x: 400, y: 300, radius: 50, fill: red, draggable: true }) layer.add(circle) layer.draw() circle.to({ x: 600, y: 400, scaleX: 2, scaleY: 2, duration: 1, easing: Konva.Easings.EaseInOut })使用Fabric.jsimport { fabric } from fabric const canvas new fabric.Canvas(canvas) const rect new fabric.Rect({ left: 100, top: 100, width: 100, height: 100, fill: blue, angle: 45 }) canvas.add(rect) rect.animate(left, 200, { duration: 1000, onChange: canvas.renderAll.bind(canvas), easing: fabric.util.ease.easeOutBounce })常见问题问题1动画卡顿解决方案使用requestAnimationFrame减少绘制调用次数使用离屏Canvas缓存问题2内存泄漏解决方案及时清理画布避免创建大量临时对象使用对象池问题3模糊问题解决方案设置canvas.width/height属性使用devicePixelRatioconst dpr window.devicePixelRatio || 1 canvas.width canvas.offsetWidth * dpr canvas.height canvas.offsetHeight * dpr ctx.scale(dpr, dpr)总结Canvas是前端动画开发的核心技术。通过学习Canvas我们可以实现复杂动画粒子系统、物理模拟创建交互式应用绘图工具、游戏数据可视化图表、图形展示性能优化批量绘制、缓存策略现在开始学习Canvas动画吧你的用户会感谢你的最后一句忠告记得使用requestAnimationFrame进行帧同步

相关文章:

Canvas动画实战:从入门到精通

Canvas动画实战:从入门到精通 前言 各位前端小伙伴,不知道你们有没有想过在浏览器中实现复杂的动画效果?Canvas可以让你实现各种炫酷的动画! 我曾经开发过一个在线绘图应用,使用Canvas实现了流畅的画笔效果和动画回放功…...

不只是跑通:用D435i和VINS-Mono做个室内小车的视觉里程计demo

从D435i到移动机器人:VINS-Mono室内视觉里程计实战指南 当Intel RealSense D435i深度相机遇上VINS-Mono这个轻量级视觉惯性里程计框架,我们能在一台简易ROS小车上实现怎样的定位与建图效果?本文将带你从硬件连接开始,逐步完成传感…...

TSN网络仿真入门:除了OMNeT++,这几个开源框架(NeSTiNg/CoRE4INET)到底该怎么选?

TSN网络仿真框架深度选型指南:从OMNeT生态到实战避坑 引言:当TSN遇见仿真工具丛林 在工业自动化与车载网络领域,时间敏感网络(TSN)正成为实时通信的基础设施。但部署前的验证环节往往让研究者陷入两难——直接搭建物理测试床成本高昂&#xf…...

SmartNIC与DPU技术解析:计算卸载与性能优化实践

1. SmartNIC与DPU技术概述在数据中心和高性能计算领域,网络瓶颈一直是制约系统性能的关键因素。传统网卡仅负责简单的数据包收发,而现代计算密集型应用需要更智能的网络处理能力。这就是SmartNIC(智能网卡)和DPU(数据处…...

【鸿蒙 HarmonyOS】从零到一:Node.js 环境配置与 DevEco Studio 无缝对接指南

1. 为什么需要Node.js环境? 如果你刚刚接触鸿蒙开发,可能对DevEco Studio里弹出的"Node.js not found"提示感到困惑。其实Node.js在鸿蒙生态中扮演着重要角色——它不仅是npm包管理器的运行环境,更是鸿蒙应用编译工具链的基础依赖。…...

你还在手动调参?——用Python自动化脚本批量生成表现主义变体并智能评分(GitHub开源已验证)

更多请点击: https://intelliparadigm.com 第一章:你还在手动调参?——用Python自动化脚本批量生成表现主义变体并智能评分(GitHub开源已验证) 表现主义图像生成常依赖艺术家风格参数(如笔触强度、色域饱和…...

抖音无水印下载器终极指南:两种高效方法实现高清视频保存

抖音无水印下载器终极指南:两种高效方法实现高清视频保存 【免费下载链接】douyin_downloader 抖音短视频无水印下载 win编译版本下载:https://www.lanzous.com/i9za5od 项目地址: https://gitcode.com/gh_mirrors/dou/douyin_downloader 抖音无水…...

ARM TLBIP指令解析与应用实践

1. ARM TLBIP指令深度解析在ARMv8/v9架构中,TLB(Translation Lookaside Buffer)作为内存管理单元(MMU)的核心组件,负责缓存虚拟地址到物理地址的转换结果。当页表发生变更时,必须及时使TLB中对应的缓存条目失效,以确保内存访问的正…...

FanControl深度技术解析:构建精准智能的风扇控制体系

FanControl深度技术解析:构建精准智能的风扇控制体系 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/…...

UE5保姆级教程:用Electra Player插件在场景里放视频,从导入MP4到带声音播放

UE5实战指南:Electra Player插件实现场景视频播放全流程解析 在虚幻引擎5的沉浸式场景中,视频播放功能已成为增强环境叙事的关键技术。无论是商场里的动态广告屏、科幻场景中的全息投影,还是角色手持设备的交互界面,流畅的视频播放…...

瑞为技术获IPO备案:年营收4.4亿 亏损6815万

雷递网 雷建平 5月15日厦门瑞为信息技术股份有限公司(简称“瑞为技术”)日前获IPO备案,拿到了上市钥匙。与瑞为技术一同拿到上市备案的公司还有上海仙工智能科技股份有限公司、江西齐云山食品股份有限公司、广东鼎泰高科技术股份有限公司。年…...

3步完成Android Studio中文界面配置:告别英文困扰,提升开发效率

3步完成Android Studio中文界面配置:告别英文困扰,提升开发效率 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack…...

高途CFO沈楠辞职 高级副总裁罗斌晋升为首席运营官

雷递网 乐天 5月15日高途(NYSE: GOTU)日前宣布管理层调整。高途称,公司CFO沈楠由于个人原因已递交辞呈,2026年5月31日生效。沈楠辞职后三个月内继续担任公司顾问,以确保平稳过渡。高途战略主管徐步青将负责公司资本市场相关事宜,高…...

智芯MCU开发环境实战:从零搭建Keil与JLink生态

1. 环境准备:从零开始的智芯MCU开发之旅 第一次拿到智芯Z20K1x系列开发板时,我和大多数嵌入式开发者一样,迫不及待想点亮第一个LED。但现实往往比想象复杂——当我打开Keil准备大展拳脚时,发现芯片列表里根本找不到智芯的身影。这…...

《Java 100 天进阶之路》第23篇:缓冲区数据结构 ByteBuffer

第23篇:缓冲区数据结构 ByteBuffer 📌 系列导航:《Java 100 天进阶之路》完整目录 | ⬅️ 上一篇:第22篇:Java字符串简介 | ➡️ 下一篇:第24篇:Java枚举类型 enum 用法👈 待发布 一…...

免费Minecraft基岩版启动器终极指南:突破官方限制的完整解决方案

免费Minecraft基岩版启动器终极指南:突破官方限制的完整解决方案 【免费下载链接】BedrockLauncher 项目地址: https://gitcode.com/gh_mirrors/be/BedrockLauncher 还在为Minecraft基岩版官方启动器的功能限制而困扰吗?想要像Java版那样自由管理…...

硬件工程师的‘第一板’:从最小系统设计到PCB Layout的STM32实战指南

STM32最小系统设计实战:从原理到PCB的工程化思维 作为一名硬件工程师,第一次独立完成PCB设计时的忐忑至今记忆犹新。那块承载着STM32最小系统的绿色电路板,不仅是我职业生涯的"第一板",更是一次从理论到实践的完整跨越。…...

ThinkPad T480黑苹果终极方案:从硬件兼容到系统优化的完全手册

ThinkPad T480黑苹果终极方案:从硬件兼容到系统优化的完全手册 【免费下载链接】t480-oc 💻 Lenovo ThinkPad T480 / T580 / X280 Hackintosh (macOS Monterey 12.x - Sequoia 15.x) - OpenCore 项目地址: https://gitcode.com/gh_mirrors/t4/t480-oc …...

基于eNSP的园区网络高可用与安全隔离综合实验

1. 实验背景与核心价值 园区网络作为企业数字化转型的基础设施,其稳定性和安全性直接关系到日常运营效率。记得去年参与某金融机构网络改造项目时,他们的核心业务系统因为单点故障导致全网瘫痪4小时,直接损失超过百万。这个案例让我深刻认识到…...

不只是调色板:深入Cadence Allegro颜色配置文件的保存与复用逻辑(SPB17.4实战)

不只是调色板:深入Cadence Allegro颜色配置文件的保存与复用逻辑(SPB17.4实战) 在PCB设计领域,颜色配置往往被视为一种"视觉装饰"——直到某天你接手一个来自同事的工程文件,发现所有网络、层叠和元件都以难…...

libhv实战:手把手教你用C++写一个带自动重连的WebSocket客户端(附避坑指南)

libhv实战:构建高可靠WebSocket客户端的工程化实践 在实时数据采集和监控系统中,WebSocket客户端的稳定性直接决定了业务连续性。当网络出现闪断、服务端重启或负载波动时,简单的连接断开可能导致关键数据丢失。libhv作为高性能网络库&#x…...

3步完成Python界面设计:可视化拖拽工具完全指南

3步完成Python界面设计:可视化拖拽工具完全指南 【免费下载链接】tkinter-helper 为tkinter打造的可视化拖拽布局界面设计小工具 项目地址: https://gitcode.com/gh_mirrors/tk/tkinter-helper 还在为Python界面开发而烦恼吗?手动编写Tkinter代码…...

从“白点”到模型:用通俗语言拆解玻纤布(如1078)在SI仿真中的正确建模姿势

从“白点”到模型:信号完整性仿真中的玻纤布建模实战指南 在高速PCB设计领域,信号完整性(SI)工程师常常需要面对一个看似微小却影响深远的问题:那些在显微镜下呈现为"白点"的玻璃纤维束,究竟应该…...

CanFestival实战:从心跳、TPDO/RPDO配置到回调函数的完整链路解析

1. CanFestival协议栈基础认知 第一次接触CanFestival时,我也被各种专业术语搞得晕头转向。简单来说,它就是个开源的CANopen协议栈实现,专门用于嵌入式设备间的通信。就像两个说同一种方言的人能顺畅交流一样,CanFestival让不同厂…...

免费跨平台绘图神器:draw.io桌面版终极使用指南

免费跨平台绘图神器:draw.io桌面版终极使用指南 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop 还在为不同系统间的图表文件兼容性而烦恼吗?&#x1f91…...

轻量级AI工具库aiclublight:从零解析微型深度学习框架的设计与实现

1. 项目概述:一个轻量级AI工具库的诞生最近在GitHub上闲逛,发现了一个挺有意思的项目,叫aiclublight,作者是Dimks777。光看名字,大概就能猜到,这应该是一个和人工智能俱乐部或者AI相关的、主打轻量化的工具…...

开源机械爪OpenClaw UBI:从3D打印到Arduino控制的低成本机器人抓取方案

1. 项目概述:一个基于开源硬件的机械爪设计与实现最近在整理工作室的物料时,翻出了几个闲置的步进电机和一堆3D打印件,这让我想起了几年前一个挺有意思的项目——OpenClaw UBI。这是一个在开源硬件社区里流传的、基于通用构建接口&#xff08…...

开源机器人夹爪任务控制台:架构设计与工程实践全解析

1. 项目概述:从“OpenClaw 任务控制”看开源机器人控制台的演进最近在机器人开发社区里,一个名为abhi1693/openclaw-mission-control的项目引起了我的注意。乍一看这个标题,你可能会联想到科幻电影里那些布满屏幕、控制着庞大机械臂的指挥中心…...

Mastra框架全解析:构建AI应用的全栈开发实践

1. 项目概述:一个面向AI应用开发的“全栈式”框架最近在折腾AI应用开发的朋友,估计都绕不开一个核心痛点:如何把大语言模型(LLM)的能力,稳定、高效、低成本地集成到自己的产品里。从调用API、管理对话状态、…...

AI Native Web 开发实战:从零构建智能应用

AI Native Web 产品实战指南:从概念到落地的完整路线做了大半年 AI 应用开发之后,我发现一个现象:很多人知道 “AI Native” 这个词,但真要动手做一个 AI Native 的 Web 产品,脑子里是一团浆糊的。这篇文章就是想把这块…...