canvas绘制心形分两类:参数方程采样(x=16·sin³t, y=13·cos t−5·cos 2t−2·cos 3t−cos 4t,t∈[0,2π],需坐标平移与y轴翻转)和贝塞尔拟合(双三次曲线拼接,适合动画变形);优化要点包括禁用抗锯齿、复用path2d、缩放实现心跳动效。

Canvas 绘制心形图案,核心在于把数学定义的曲线准确转为像素路径。关键不在于“画多像”,而在于“怎么算得稳、画得准、改得快”。常用路径生成方式就两类:贝塞尔拟合(适合控制、轻量)和参数方程采样(适合标准、可动画)。
用参数方程描点生成心形路径
最经典的心形参数方程是:
x = 16·sin³t,y = 13·cos t − 5·cos 2t − 2·cos 3t − cos 4t
这个公式生成的轮廓对称、饱满,接近手绘心形。实际绘制时要注意三点:
- 参数 t 从 0 到 2π,步长建议取 0.01~0.03,太大会锯齿,太小无意义
- 计算出的 x、y 是相对坐标,需平移至画布中心(如
centerX + x * scale) - y 轴方向要翻转(Canvas y 向下为正),所以实际用
y = centerY - y * scale
用贝塞尔曲线手动拟合心形
不用数学公式,靠两个三次贝塞尔曲线拼出左右半边,再闭合——更适合需要动态调整曲率或做变形动画的场景。
- 起点通常设在顶部尖点(如
moveTo(200, 100)) - 右半边:用
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endX, endY)拉出弧线到底部中心 - 左半边:镜像控制点,终点回到顶部,形成闭环
- 调用
closePath()再fill(),比单纯描边更可靠
提升绘制质量的实用细节
光画出来还不够,真实项目中常遇到这些情况:
- 缩放失真?别用 CSS 改 canvas 尺寸,直接设置
canvas.width和canvas.height属性 - 边缘发虚?关掉抗锯齿:
ctx.imageSmoothingEnabled = false(对线条有效) - 想加渐变填充?用
createRadialGradient(x, y, 0, x, y, radius),从中心向外过渡更自然 - 多个爱心飘落?先用
new Path2D()构建一次路径,后续直接ctx.fill(path)复用,性能更好
动起来:心跳效果只需两行缩放
让爱心轻微脉动,不需要复杂动画库。核心是周期性缩放:
- 在
requestAnimationFrame循环里,计算:scale = 1 + 0.08 * Math.sin(Date.now() / 150) - 绘制前执行:
ctx.save(); ctx.translate(centerX, centerY); ctx.scale(scale, scale); ctx.translate(-centerX, -centerY);











