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

如何在HTML Canvas中绘制圆角星形?

绘制圆角星形的实现方案

问题分析

你当前的代码实际绘制的是30边形,而非星形,且未包含圆角处理逻辑。下面先整理你找到的Android平台圆角路径核心思路,再给出适配Canvas的圆角星形实现代码。

Android平台圆角路径核心思路(翻译整理)

该方案通过圆弧过渡实现路径转角的圆角效果,核心步骤为:

  • 针对路径上连续的三个顶点(前顶点A、当前顶点B、后顶点C),计算AB、BC两条边的方向向量
  • 从B点出发,沿AB反向、BC方向各截取一段长度等于圆角半径的距离,得到两个过渡点P、Q
  • 以B为参考点,用圆弧连接P、Q两点,替代原本的尖锐转角B
  • 依次处理所有顶点,最终形成带圆角的闭合路径

Canvas实现圆角星形代码

let canvas: HTMLCanvasElement | undefined = undefined;

// 角度转弧度
function toRadians(degrees: number) {   
    return degrees * (Math.PI / 180);
}

// 计算两点间距离
function getDistance(x1: number, y1: number, x2: number, y2: number) {
    return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

// 绘制圆角星形
function drawRoundedStar(centerX: number, centerY: number, outerRadius: number, innerRadius: number, points: number, cornerRadius: number) {
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#000';
    ctx.fillStyle = '#fff';

    const angleStep = toRadians(360 / points / 2); // 星形步长取半角
    const vertices: {x: number, y: number}[] = [];

    // 生成星形交替顶点(外半径、内半径依次排列)
    for (let i = 0; i < points * 2; i++) {
        const radius = i % 2 === 0 ? outerRadius : innerRadius;
        const angle = toRadians(90) + i * angleStep; // 从顶部开始绘制
        const x = centerX + radius * Math.cos(angle);
        const y = centerY + radius * Math.sin(angle);
        vertices.push({x, y});
    }

    ctx.beginPath();
    // 遍历顶点处理圆角
    for (let i = 0; i < vertices.length; i++) {
        const curr = vertices[i];
        const prev = vertices[(i - 1 + vertices.length) % vertices.length];
        const next = vertices[(i + 1) % vertices.length];

        // 计算前边上的过渡点
        const prevDist = getDistance(prev.x, prev.y, curr.x, curr.y);
        const prevRatio = cornerRadius / prevDist;
        const pX = curr.x - (curr.x - prev.x) * prevRatio;
        const pY = curr.y - (curr.y - prev.y) * prevRatio;

        // 计算后边上的过渡点
        const nextDist = getDistance(curr.x, curr.y, next.x, next.y);
        const nextRatio = cornerRadius / nextDist;
        const qX = curr.x + (next.x - curr.x) * nextRatio;
        const qY = curr.y + (next.y - curr.y) * nextRatio;

        // 绘制线段到过渡点,再用圆弧连接到下一个过渡点
        if (i === 0) {
            ctx.moveTo(pX, pY);
        } else {
            ctx.lineTo(pX, pY);
        }
        ctx.arcTo(curr.x, curr.y, qX, qY, cornerRadius);
    }

    ctx.closePath();
    ctx.fill();
    ctx.stroke();
}

onMount(() => {
    if (canvas) {
        // 参数:中心坐标、外半径、内半径、星形角数、圆角半径
        drawRoundedStar(150, 150, 80, 40, 5, 10);
    }
});

代码说明

  • 先生成星形的交替顶点(外半径、内半径依次排列),构建基础轮廓
  • 对每个顶点,计算前后边上距离顶点为圆角半径的过渡点
  • 使用arcTo方法在过渡点间绘制圆弧,替换尖锐转角
  • 最后闭合路径并执行填充、描边操作,得到带圆角的星形

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:35:27