用canvas实现线条生长动画需控制路径绘制进度,通过requestanimationframe逐步绘制折线段,计算累计长度映射进度,动态截取子路径并支持缓动、头部高亮等增强效果。

用Canvas实现线条生长动画,核心是控制路径绘制的进度,通过定时器逐步绘制路径片段,而非一次性画完。
准备基础Canvas环境
先在HTML中创建<canvas></canvas>元素,并获取2D绘图上下文:
<canvas id="lineCanvas" width="800" height="400"></canvas>
JavaScript中初始化:
const canvas = document.getElementById('lineCanvas');<br>const ctx = canvas.getContext('2d');<br>ctx.lineWidth = 2;<br>ctx.strokeStyle = '#3b82f6';<br>ctx.lineCap = 'round';定义路径点并计算总长度
线条生长依赖路径“进度”,需预先知道整条路径的总长度。可使用贝塞尔曲线、直线段或SVG路径转点数组。简单起见,以折线为例:
const points = [<br> {x: 50, y: 200},<br> {x: 200, y: 100},<br> {x: 400, y: 250},<br> {x: 700, y: 180}<br>];手动计算累计长度(用于进度映射):
- 遍历相邻点对,用勾股定理算每段距离
- 生成一个长度累加数组
lengths,如[0, d1, d1+d2, d1+d2+d3] - 总长度
totalLength = lengths[lengths.length - 1]
按进度动态绘制路径片段
关键逻辑:给定当前进度(0~1),找出该位置落在哪一段线段上,并只绘制从起点到该位置的子路径。
- 用
requestAnimationFrame替代setInterval,保证流畅且节电 - 维护一个
progress变量(初始0,每帧递增如0.008),上限为1 - 根据
progress * totalLength查找对应线段和插值坐标 - 清空画布(
ctx.clearRect(0,0,w,h)),重绘已生长部分
示例片段(简化):
function drawSegmentUpTo(progress) {<br> const targetLen = progress * totalLength;<br> ctx.beginPath();<br> ctx.moveTo(points[0].x, points[0].y);<br> let accumulated = 0;<br> for (let i = 1; i const dx = points[i].x - points[i-1].x;<br> const dy = points[i].y - points[i-1].y;<br> const segLen = Math.sqrt(dx*dx + dy*dy);<br> if (accumulated + segLen >= targetLen) {<br> const t = (targetLen - accumulated) / segLen;<br> const x = points[i-1].x + dx * t;<br> const y = points[i-1].y + dy * t;<br> ctx.lineTo(x, y);<br> break;<br> } else {<br> ctx.lineTo(points[i].x, points[i].y);<br> accumulated += segLen;<br> }<br> }<br> ctx.stroke();<br>}增强表现力的小技巧
让生长更自然、有细节:
-
缓动效果:用
easeOutQuad等缓动函数控制 progress 增速,开头慢、结尾快 -
头部高亮:在终点处用
arc()绘制小圆点,模拟“生长头” -
虚线模拟:设置
ctx.setLineDash([5, 5]),配合lineDashOffset实现流动虚线感 - 多路径同步:封装为类,支持多个独立生长线条共存
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











