上一篇
如何用HTML5画布绘制椭圆?
- 前端开发
- 2025-06-13
- 3944
在HTML5画布中绘制椭圆可通过两种方法实现:1)使用
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle)
方法直接绘制;2)通过缩放圆形路径:先绘制正圆,再用
scale()
水平/垂直缩放形成椭圆,后者需配合
save()
/
restore()
管理状态。
在HTML5 Canvas中绘制椭圆需要一些技巧,因为Canvas API没有直接提供ellipse()
方法(直到Canvas Path2D的加入),以下是三种可靠的方法,附详细代码示例:
方法1:使用缩放变换(推荐)
<canvas id="myCanvas" width="400" height="300"></canvas> <script> const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); function drawEllipse(x, y, radiusX, radiusY, rotation = 0) { ctx.save(); // 保存当前画布状态 ctx.translate(x, y); // 平移至椭圆中心 ctx.rotate(rotation); // 旋转(弧度制) ctx.scale(radiusX, radiusY); // 缩放坐标系 ctx.beginPath(); ctx.arc(0, 0, 1, 0, Math.PI * 2); // 绘制单位圆 ctx.restore(); // 恢复原始坐标系 ctx.stroke(); } // 示例:绘制椭圆 (中心点x=200,y=150, 水平半径80, 垂直半径50, 旋转30度) drawEllipse(200, 150, 80, 50, Math.PI/6); </script>
原理:通过缩放坐标系将圆形变形为椭圆,需配合save()
/restore()
避免影响后续绘制。
方法2:贝塞尔曲线逼近
function drawEllipseBezier(x, y, radiusX, radiusY) { const kappa = 0.5522848; // 贝塞尔曲线控制点系数 const ox = radiusX * kappa; const oy = radiusY * kappa; ctx.beginPath(); ctx.moveTo(x, y - radiusY); ctx.bezierCurveTo( x + ox, y - radiusY, x + radiusX, y - oy, x + radiusX, y ); ctx.bezierCurveTo( x + radiusX, y + oy, x + ox, y + radiusY, x, y + radiusY ); ctx.bezierCurveTo( x - ox, y + radiusY, x - radiusX, y + oy, x - radiusX, y ); ctx.bezierCurveTo( x - radiusX, y - oy, x - ox, y - radiusY, x, y - radiusY ); ctx.stroke(); }
方法3:使用Path2D对象(现代浏览器)
// 创建椭圆Path2D对象 const ellipse = new Path2D(); ellipse.ellipse(200, 150, 80, 50, Math.PI/4, 0, Math.PI*2); // 绘制 ctx.stroke(ellipse); ctx.fillStyle = '#FF9800'; ctx.fill(ellipse);
参数说明:ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle)
关键注意事项
- 坐标系影响:缩放法会同时缩放线条宽度,需在缩放前调整线宽
- 性能优化:贝塞尔曲线法在动画中性能较差,静态图形可用
- 浏览器兼容性:
- Path2D支持:Chrome 55+、Firefox 52+、Edge 79+
- 传统方法支持所有Canvas浏览器
- 填充与描边:所有方法都支持
fill()
和stroke()
完整示例(缩放法优化版)
<canvas id="demoCanvas" width="500" height="400"></canvas> <script> const canvas = document.getElementById('demoCanvas'); const ctx = canvas.getContext('2d'); function drawEllipse(x, y, rx, ry, color, rotation = 0) { ctx.save(); ctx.translate(x, y); ctx.rotate(rotation); ctx.scale(rx, ry); ctx.lineWidth = 1 / Math.max(rx, ry) * 2; // 线宽自适应 ctx.beginPath(); ctx.arc(0, 0, 1, 0, Math.PI * 2); ctx.restore(); ctx.strokeStyle = color; ctx.stroke(); } // 绘制三个不同椭圆 drawEllipse(100, 100, 70, 40, 'blue'); drawEllipse(300, 200, 100, 60, 'red', Math.PI/4); drawEllipse(400, 300, 50, 80, '#0a0'); </script>
引用说明
- Canvas缩放原理参考MDN文档CanvasRenderingContext2D.scale()
- 贝塞尔系数计算基于Tim Liew的椭圆近似算法
- Path2D规范来自W3CCanvas Path2D标准
提示:对于复杂场景,推荐使用Path2D + 变换矩阵的组合方案,可在实现效果的同时保持代码可维护性,实际开发中建议封装为可复用的椭圆绘制函数。