当前位置:首页 > 前端开发 > 正文

如何用HTML5画布绘制椭圆?

在HTML5画布中绘制椭圆可通过两种方法实现:1)使用 ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle)方法直接绘制;2)通过缩放圆形路径:先绘制正圆,再用 scale()水平/垂直缩放形成椭圆,后者需配合 save()/ restore()管理状态。

在HTML5 Canvas中绘制椭圆需要一些技巧,因为Canvas API没有直接提供ellipse()方法(直到Canvas Path2D的加入),以下是三种可靠的方法,附详细代码示例:

如何用HTML5画布绘制椭圆?  第1张

方法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)


关键注意事项

  1. 坐标系影响:缩放法会同时缩放线条宽度,需在缩放前调整线宽
  2. 性能优化:贝塞尔曲线法在动画中性能较差,静态图形可用
  3. 浏览器兼容性
    • Path2D支持:Chrome 55+、Firefox 52+、Edge 79+
    • 传统方法支持所有Canvas浏览器
  4. 填充与描边:所有方法都支持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 + 变换矩阵的组合方案,可在实现效果的同时保持代码可维护性,实际开发中建议封装为可复用的椭圆绘制函数。

0