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

如何在JavaScript中获取正多边形最大宽度并适配边界框?

正多边形适配正方形边界框的实现问题

我一直在用数学公式绘制正多边形(各边长度和角度均相等的多边形),但尚未实现让多边形基于其最长尺寸适配指定宽度的正方形边界框,确保不会超出边界。

示例场景:粉色多边形的横向宽度(黑色线条标注)短于蓝色多边形的横向宽度(橙色线条标注),黄色正方形边界框内,粉色多边形需居中放置,蓝色多边形的边角则要贴合边界框边缘。

我尝试了以下两个距离公式来测量多边形的"最大距离",但未达到预期效果:

export function calculatePolygonHeight(
  sides: number,
  radius: number,
): number {
  // 确保边数合法
  if (sides < 3) {
    throw new Error('Number of sides must be at least 3')
  }

  // 计算多边形高度
  const height = radius * (1 + Math.cos(Math.PI / sides))

  return height
}

export function distanceBetweenVertices({
  sides,
  radius,
  distance,
}: {
  sides: number
  radius: number
  distance: number
}): number {
  if (sides < 3) {
    throw new Error('A polygon must have at least 3 sides.')
  }
  if (distance < 1 || distance >= sides) {
    throw new Error('distance must be between 1 and sides-1.')
  }

  const angle = (distance * Math.PI) / sides
  return 2 * radius * Math.sin(angle)
}

我使用以下代码计算SVG多边形路径:

function computePolygonPoints({
  width,
  height,
  sides,
  strokeWidth,
  rotation = 0,
}: {
  width: number
  height: number
  sides: number
  strokeWidth: number
  rotation?: number
}) {
  const centerX = width / 2
  const centerY = height / 2
  const radiusX = width / 2
  const radiusY = height / 2
  const offsetX = strokeWidth / 2
  const offsetY = strokeWidth / 2

  const rotationRad = (rotation * Math.PI) / 180

  const points = Array.from({ length: sides }, (_, i) => {
    const angle = (i * 2 * Math.PI) / sides + ANGLE
    const x = centerX + radiusX * Math.cos(angle)
    const y = centerY + radiusY * Math.sin(angle)

    // 围绕中心旋转
    const rotatedX =
      centerX +
      (x - centerX) * Math.cos(rotationRad) -
      (y - centerY) * Math.sin(rotationRad)
    const rotatedY =
      centerY +
      (x - centerX) * Math.sin(rotationRad) +
      (y - centerY) * Math.cos(rotationRad)

    return { x: rotatedX, y: rotatedY }
  })

  const minX = Math.min(...points.map(p => p.x))
  const minY = Math.min(...points.map(p => p.y))

  const adjustedPoints = points.map(p => ({
    x: offsetX + p.x - minX,
    y: offsetY + p.y - minY,
  }))

  return adjustedPoints
}

这段代码能正确绘制多边形,但在处理描边宽度时存在问题:描边以边缘为中心,一半在多边形区域外,一半在内部。

我的思路是:

  • 获取多边形的最大距离;
  • 偏移strokeWidth/2(避免描边被截断);
  • 将最大距离(宽度)缩小strokeWidth,使绘制的多边形略小于要求尺寸,添加描边后视觉效果符合预期。

例如,我需要绘制宽度为256px、描边宽度为8px的多边形,如何实现任意旋转时都能在256x256的边界框内居中并尽可能填满?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:06:04