You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CanvasRenderingContext2D绘制两个圆形的交集区域

绘制两个圆形的公共区域(可缩放)解决方案

要实现可缩放的两圆公共区域绘制(从完整圆收缩到一个点),核心是通过几何计算确定两圆交点,再用CanvasPath接口的方法拼接出交集路径,具体步骤如下:

1. 几何计算:确定两圆参数与交点

假设使用两个等半径的圆(简化缩放逻辑),定义核心参数:

  • 固定半径 r:两个圆的半径一致
  • 圆心距 d:控制缩放的关键变量,取值范围 0 ≤ d ≤ 2r
    • d=0:两圆心重合,交集为完整圆形
    • d=2r:两圆外切,交集为一个点
    • 0 < d < 2r:两圆相交,交集为月牙形区域

交点坐标计算

设交集区域中心为 (cx, cy),将两圆心沿x轴对齐简化计算(可通过旋转适配任意方向):

  • 圆A圆心:(cx - d/2, cy)
  • 圆B圆心:(cx + d/2, cy)

通过几何公式推导交点坐标:

// 计算交点到圆心连线的垂直距离
const h = Math.sqrt(r * r - (d/2) * (d/2));
// 两个交点的坐标
const p1 = { x: cx, y: cy + h };
const p2 = { x: cx, y: cy - h };

同时确定每个圆需要绘制的弧段角度:

  • 圆A取从p2到p1的顺时针弧
  • 圆B取从p1到p2的顺时针弧

2. 使用CanvasPath接口绘制交集路径

仅用允许的moveTo()、arc()、closePath()方法构建路径,代码示例:

function drawIntersection(ctx, cx, cy, r, d) {
  if (d <= 0) {
    // 圆心距为0,绘制完整圆
    ctx.beginPath();
    ctx.arc(cx, cy, r, 0, Math.PI * 2);
    ctx.fillStyle = 'red';
    ctx.fill();
    return;
  }
  if (d >= 2 * r) {
    // 圆心距等于2r,绘制一个点
    ctx.beginPath();
    ctx.arc(cx, cy, 1, 0, Math.PI * 2);
    ctx.fillStyle = 'red';
    ctx.fill();
    return;
  }

  // 计算交点与圆心坐标
  const h = Math.sqrt(r * r - (d/2) * (d/2));
  const p1 = { x: cx, y: cy + h };
  const p2 = { x: cx, y: cy - h };
  const x1 = cx - d/2;
  const x2 = cx + d/2;
  const y = cy;

  // 构建交集路径
  ctx.beginPath();
  ctx.moveTo(p1.x, p1.y);
  // 绘制圆A的下半弧(从p1到p2)
  ctx.arc(x1, y, r, Math.PI/2, -Math.PI/2, true);
  // 绘制圆B的上半弧(从p2到p1)
  ctx.arc(x2, y, r, -Math.PI/2, Math.PI/2, true);
  ctx.closePath();
  
  ctx.fillStyle = 'red';
  ctx.fill();
}

3. 实现缩放控制

通过修改d的值(从0到2r)即可动态调整交集大小,示例动画逻辑:

// 初始化参数
let d = 0;
let direction = 1;
const radius = 50;
const maxD = 2 * radius;
const canvas = document.getElementById('your-canvas');
const ctx = canvas.getContext('2d');

// 动态缩放动画
function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawIntersection(ctx, canvas.width/2, canvas.height/2, radius, d);
  
  d += direction * 0.5;
  if (d <= 0 || d >= maxD) {
    direction *= -1;
  }
  requestAnimationFrame(animate);
}
animate();

上述代码完全使用你指定的CanvasPath接口方法,适配Chart.js插件开发场景。

内容的提问来源于stack exchange,提问作者eKangu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 11:37:56