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
相关产品推荐
相关产品推荐

