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

Canvas实现动态波浪时如何调整波形中间位置的上下偏移?

Canvas波浪效果对齐参考图修正方案

目标波浪效果参考
现有代码无法匹配参考效果的核心原因:

  • 动画循环被注释:animate函数内的requestAnimationFrame(animate)被注释,仅会渲染第一帧,无法产生连续流动效果
  • 波浪路径闭合逻辑错误:绘制完波浪曲线后直接连接到离屏画布右上角,未先拉至画布右下角再闭合路径,导致填充区域偏移,波浪中线位置完全错位
  • 绘制逻辑存在硬编码魔数:循环中134、200、x/100等硬编码值未和画布宽度做映射,波浪密度、位置计算偏差
  • 画布与渐变范围设置错误:离屏画布高度、渐变填充范围未匹配波浪振幅,导致顶部填充不全、底部漏空

修正后完整代码

HTML代码

<canvas id="wave"></canvas>

JavaScript代码

const canvas = document.getElementById('wave');
const ctx = canvas.getContext('2d');
const cw = window.innerWidth;
const ch = window.innerHeight;

canvas.width = cw;
canvas.height = ch;

let offsetX = 0;
// 此处midWaveY设为屏幕高度75%位置,和参考图波浪中线对齐
const waveCanvas = makeWave(canvas.width, ch * 0.75, 60, 3, 'lightskyblue', 'cornflowerblue');

requestAnimationFrame(animate);

function animate() {
    ctx.clearRect(0, 0, cw, ch);
    ctx.drawImage(waveCanvas, offsetX, 0);
    offsetX -= 1;
    if (offsetX < -waveCanvas.width / 2) {
        offsetX = 0;
    }
    // 恢复动画循环调用
    requestAnimationFrame(animate);
}

function makeWave(width, midWaveY, amplitude, wavesPerWidth, grad0, grad1) {
    const PI2 = Math.PI * 2;
    const totalRadian = PI2 * wavesPerWidth;
    const offscreenCanvas = document.createElement('canvas');
    const offscreenCtx = offscreenCanvas.getContext('2d');
    // 离屏画布做2倍屏宽,保证无缝滚动
    offscreenCanvas.width = width * 2;
    offscreenCanvas.height = midWaveY + amplitude;
    // 渐变覆盖整个填充区域
    const grad = offscreenCtx.createLinearGradient(0, 0, 0, offscreenCanvas.height);
    grad.addColorStop(0, grad0);
    grad.addColorStop(1, grad1);

    offscreenCtx.beginPath();
    offscreenCtx.moveTo(0, 0);
    // 逐像素绘制正弦波浪曲线
    for (let x = 0; x <= offscreenCanvas.width; x++) {
        const rad = totalRadian * x / width;
        offscreenCtx.lineTo(x, Math.sin(rad) * amplitude + midWaveY);
    }
    // 正确闭合路径:波浪线终点→右下角→左下角→起点
    offscreenCtx.lineTo(offscreenCanvas.width, offscreenCanvas.height);
    offscreenCtx.lineTo(0, offscreenCanvas.height);
    offscreenCtx.closePath();
    offscreenCtx.fillStyle = grad;
    offscreenCtx.fill();
    return offscreenCanvas;
}

效果微调参数

如果需要调整波浪形态,直接修改对应参数即可:

  • midWaveY:控制波浪中线的垂直位置,数值越大波浪整体越靠下
  • amplitude:控制波浪起伏高度,数值越大浪的高低差越大
  • wavesPerWidth:控制单屏内的波浪数量,数值越大波浪越密集
  • offsetX -= 1:控制波浪流动速度,数值越大流动越快

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:45:37