用quadraticCurveTo以中间点为控制点绘制二次贝塞尔曲线实现平滑折线,动态追加时缓存最近3点、仅重绘新增段并保持起点连贯,配合双端队列管理、lineCap/lineJoin优化及局部清屏提升性能。
Canvas绘制动态折线图时,原生lineTo只能画直线段,要实现视觉上自然的平滑曲线,需用贝塞尔曲线(尤其是bezierCurveTo或quadraticCurveTo)替代折线连接,再配合数据流更新与重绘控制。
对连续数据点序列 [p0, p1, p2, ...],以每个中间点 p1 为控制点,将 p0→p1→p2 转换为一段平滑弧线。Canvas中调用 quadraticCurveTo(p1.x, p1.y, p2.x, p2.y) 即可——起点为前一个端点(需先moveTo(p0)),控制点是当前数据点,终点是下一个数据点。
p1 偏移 10% 向量方向,避免拐角过尖新数据持续流入(如每100ms新增一个点),不能每次清空重绘整条线——否则会闪烁且失去“流动感”。应只绘制新增的一小段,并利用上一时刻的末尾点作为新曲线的起点。
lastPoints = [p_{n-2}, p_{n-1}, p_n]),新增p_{n+1}后,用p_{n-1}作控制点、p_n作起点、p_{n+1}作终点调用quadraticCurveTo
moveTo设起点,后续仅追加quadraticCurveTo,不重复beginPath和stroke外层操作Canvas默认开启抗锯齿,但缩放或高密度点可能导致边缘模糊或性能下降。可通过调整线条宽度、关闭图像平滑或分段渲染缓解。
立即学习“前端免费学习笔记(深入)”;
ctx.lineCap = 'round'和ctx.lineJoin = 'round',让线段衔接处更圆润ctx.imageSmoothingEnabled = false(这会影响文字和图片,非必要不关);改用ctx.lineWidth = 1.5提升视觉清晰度ctx.clearRect()仅擦除旧线末端+新线区域,而非全屏清空以下逻辑可嵌入requestAnimationFrame循环中:
dataPoints,每次推入新点并限制长度(如dataPoints.length > 100 && dataPoints.shift())i = 2 to dataPoints.length-1,对每组(i-2, i-1, i)调用quadraticCurveTo(data[i-1], data[i]),起始moveTo(data[0])
lineWidth或渐变色