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

HTML Canvas元素接触检测:实现正弦波形覆盖文本时自动切换字体颜色

实现方案

这里提供两种可行的实现路径,你可以根据自己的需求选择:

方案一:CSS混合模式实现(零JS修改,成本最低)

这个方案利用CSS的混合模式自动实现文字和背景的反色效果,完全不需要改动现有JS逻辑,仅需修改3行CSS:

/* 新增body背景,避免透明透出异常颜色 */
body {
    margin: 0;
    padding: 0;
    background: #fff; /* 新增这行 */
}
/* 修改h1样式 */
h1 {
    text-align: center;
    color: #000; /* 把原有white改成black */
    mix-blend-mode: difference; /* 新增这行 */
}

实现原理:

  • 波浪未覆盖的区域canvas为透明,透出底层body的白色背景,黑色文字和白色背景做差值混合后显示为白色
  • 波浪覆盖的区域canvas为黑色,黑色文字和黑色背景做差值混合后显示为黑色,刚好匹配你要的效果

方案二:JS检测覆盖状态实现(灵活度更高)

如果后续需要自定义触发逻辑(比如覆盖比例超过50%才变色、变色时加过渡动画等),可以用JS实时检测波浪和文字的重叠状态:

修改步骤:

  1. 先在JS代码中提前获取h1元素:
const title = document.querySelector('h1');
  1. 在drawWave函数末尾新增重叠检测逻辑:
const drawWave = () => {
    // 原有代码保持不变
    // ... 原有drawWave代码 ...

    // 新增以下检测逻辑
    const titleRect = title.getBoundingClientRect();
    // 计算标题水平范围内的波浪最高、最低位置
    let waveMinY = Infinity;
    let waveMaxY = -Infinity;
    // 只遍历标题水平覆盖的x范围,不用遍历全宽,性能更好
    for (let x = titleRect.left; x < titleRect.right; x++) {
        const y = wave.y + Math.sin(x * wave.length + increment) * wave.amplitude;
        waveMinY = Math.min(waveMinY, y);
        waveMaxY = Math.max(waveMaxY, y);
    }
    // 判断波浪和标题垂直范围是否有重叠
    const isOverlap = !(waveMaxY < titleRect.top || waveMinY > titleRect.bottom);
    title.style.color = isOverlap ? '#000' : '#fff';
};

额外优化建议
  • 现有波浪绘制的for循环步长为1,宽屏设备下性能损耗较高,可以把步长改成23,视觉上几乎没有差异,绘制效率能提升23倍:
    for (let i = 0; i < canvas.width; i+=2) { // 把i++改成i+=2
      ctx.lineTo(i, wave.y + Math.sin(i * wave.length + increment) * wave.amplitude);
    }
    
  • 窗口resize事件加防抖,避免频繁重设canvas尺寸导致卡顿
  • 你已经引入了dat.gui,可以把wave的振幅、频率、位置等参数绑定到控制面板,调试参数更方便

内容的提问来源于stack exchange,提问作者Un Jin Jang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 04:45:06