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

HTML Canvas六边形正弦波动画:如何修正卷曲对角线?

解决六边形波动画对角线卷曲问题:利用wvx实现直边

问题根源

你遇到的对角线卷曲,本质是每个顶点的波动偏移独立计算(比如单独给每个顶点加sin(wvx + angle)类的偏移),导致相邻顶点的波动曲线没有线性关联,连接后自然呈现卷曲状态。要利用wvx实现直边,核心是让相邻顶点的波动偏移保持线性衔接,而非各自独立。

解决方案1:相位分组+线性插值

将六边形的6个顶点分为3组对边,每组对边共享由wvx生成的波动相位,相邻边的顶点偏移通过线性插值衔接,确保边的线性:

const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 100;
const waveAmplitude = 20;
const sides = 6;

// 用wvx生成3组对边的基础相位
const basePhase = wvx;
const phaseGroups = [basePhase, basePhase + Math.PI/3, basePhase + 2*Math.PI/3];

const vertices = [];
for (let i = 0; i < sides; i++) {
  const angle = (Math.PI * 2 / sides) * i;
  const groupIdx = Math.floor(i / 2);
  const currentPhase = phaseGroups[groupIdx];
  const nextPhase = phaseGroups[(groupIdx + 1) % phaseGroups.length];
  
  // 偶数顶点用当前组相位,奇数顶点用当前组与下一组的线性插值
  const interp = i % 2;
  const offsetX = (1 - interp) * Math.sin(currentPhase) * waveAmplitude + interp * Math.sin(nextPhase) * waveAmplitude;
  const offsetY = (1 - interp) * Math.cos(currentPhase) * waveAmplitude + interp * Math.cos(nextPhase) * waveAmplitude;
  
  const x = centerX + radius * Math.cos(angle) + offsetX;
  const y = centerY + radius * Math.sin(angle) + offsetY;
  vertices.push([x, y]);
}

// 绘制六边形
ctx.beginPath();
vertices.forEach(([x, y], idx) => idx === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y));
ctx.closePath();
ctx.stroke();

解决方案2:边同步偏移

固定六边形的基础顶点,以wvx控制每条边的垂直偏移量,让同一条边的两个顶点偏移量完全一致,确保边始终为直线:

const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 100;
const waveAmplitude = 20;
const sides = 6;

// 预计算六边形基础顶点
const baseVertices = [];
for (let i = 0; i < sides; i++) {
  const angle = (Math.PI * 2 / sides) * i;
  baseVertices.push([
    centerX + radius * Math.cos(angle),
    centerY + radius * Math.sin(angle)
  ]);
}

// 用wvx计算全局波动偏移量
const waveOffset = Math.sin(wvx) * waveAmplitude;

const vertices = baseVertices.map(([x, y], idx) => {
  const nextIdx = (idx + 1) % sides;
  // 计算当前边的垂直方向单位向量
  const dx = baseVertices[nextIdx][0] - x;
  const dy = baseVertices[nextIdx][1] - y;
  const edgeLength = Math.sqrt(dx*dx + dy*dy);
  const perpX = -dy / edgeLength;
  const perpY = dx / edgeLength;
  
  // 顶点向边的垂直方向偏移相同距离
  return [x + perpX * waveOffset, y + perpY * waveOffset];
});

// 绘制六边形
ctx.beginPath();
vertices.forEach(([x, y], idx) => idx === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y));
ctx.closePath();
ctx.stroke();

关键原理

两种方案的核心都是通过wvx统一控制波动的节奏,确保同一条边的两个顶点偏移量线性相关:

  • 方案1通过相位分组+插值,让相邻顶点的波动平滑过渡,边自然保持直线;
  • 方案2直接让同边顶点偏移量一致,从根源保证边的线性属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:26:19