mcpField
S
shaders-cursor-ripples

shaders-cursor-ripples

github.com/mengto设计与 UI7.1k1.4k 次安装3 天前更新
代码仓库

关于 shaders-cursor-ripples

这是一项编码技能,用于在保留页面内容的同时,为现有图像添加 Shaders 的 CursorRipples 效果,并提供无障碍回退。

主要功能

  1. 01按框架选择 Shaders 导入路径
  2. 02由光标驱动的图像扭曲
  3. 03检查 WebGPU 和动态偏好
  4. 04延迟加载着色器并保留回退
  5. 05图层组织与验证指南

适用场景

  1. 01为现有图像添加波纹效果
  2. 02替换自定义聚光灯揭示效果
  3. 03在不支持 WebGPU 时保留媒体可用性
  4. 04检查减少动态效果与指针行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mengto/skills --skill shaders-cursor-ripples

安装后在 Claude Code 中输入/shaders-cursor-ripples确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

REFERENCES.md
agents/
openai.yaml
assets/react/
cursor-ripple-media.css
cursor-ripple-shader.tsx

详细介绍

Shaders Cursor Ripples

核心约定

  1. 保留现有页面、内容和语义图像。
  2. 安装 shaders,并从当前框架的子路径导入。
  3. 通过一个 Shader canvas 渲染源图像。
  4. 将 CursorRipples 放在 ImageTexture 后面,以便对该图像进行后处理。
  5. 在根节点上保留 toneMapping="aces"。
  6. 让 Shaders 跟踪光标。移除自定义聚光坐标、径向遮罩、重复的显露图像和指针动画循环。
  7. 在 canvas 下方保留一张真实图像,作为无障碍加载和 WebGPU 回退。
  8. 在减少动态效果或不支持 WebGPU 时禁用着色器。
  9. 延迟加载着色器代码,避免库增大初始页面包。

如果用户只要求着色器效果,不要照搬参考中的飘带、团块、辉光、排版、布局、文案、颜色或视觉标识。不要用 Shaders 的 Water 组件替代:CursorRipples 是交互式图像位移效果。

编辑前检查

  • 找到真实的媒体包装器、图像 URL、裁剪方式、叠加层、z-index 和现有动态效果。
  • 确认包装器具有非零的实际渲染宽度和高度。
  • 搜索旧的显露代码,例如 data-reveal-hover、mask-image: radial-gradient、重复图像、requestAnimationFrame 和手动指针监听器。
  • 保留无关的视差或入场动态效果,除非它们与着色器 canvas 冲突。
  • 如果 shaders 包可能已更新,请检查已安装的版本和当前框架 API。

安装

npm install shaders

从 shaders/react、shaders/vue、shaders/svelte 或 shaders/solid 导入。对于 Vite 项目,切勿将 shaders 添加到 optimizeDeps.exclude;它的 CommonJS 依赖需要由 Vite 预打包。通常无需配置 optimizeDeps。

在商业发布前,请核实 Shaders 当前的许可条款。

必需的组合方式

保留以下组件顺序和值:

<Shader toneMapping="aces">
  <ImageTexture url={imageUrl} objectFit="cover" />
  <CursorRipples decay={7.3} radius={0.6} />
</Shader>

以此为基准,然后再调整 intensity、chromaticSplit 或 edges。除非用户明确要求参考中的生成式艺术作品,否则不要添加 SolidColor、Blob、Form3D、GaborNoise、Glow 或其他生成器。

对于 React,请复制并调整 assets/react/cursor-ripple-shader.tsx 和 assets/react/cursor-ripple-media.css。

客户端与回退模式

仅当浏览器确认支持 WebGPU 且允许动态效果时,才挂载着色器:

const CursorRippleShader = lazy(() => import("./cursor-ripple-shader"));

const [shaderEnabled, setShaderEnabled] = useState(false);
const [shaderReady, setShaderReady] = useState(false);

useEffect(() => {
  const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");

  const sync = () => {
    const enabled = "gpu" in navigator && !reduceMotion.matches;
    setShaderEnabled(enabled);
    if (!enabled) setShaderReady(false);
  };

  sync();
  reduceMotion.addEventListener("change", sync);
  return () => reduceMotion.removeEventListener("change", sync);
}, []);

在包装器中保留语义图像,然后叠加延迟加载的着色器:

<figure className="cursor-ripple-media">
  <img
    className="cursor-ripple-media__fallback"
    src={imageUrl}
    alt={meaningfulAlt}
    width={width}
    height={height}
  />

  {shaderEnabled ? (
    <Suspense fallback={null}>
      <CursorRippleShader
        imageUrl={imageUrl}
        ready={shaderReady}
        onReady={() => setShaderReady(true)}
      />
    </Suspense>
  ) : null}
</figure>

对于 Next.js,也可以使用 ssr: false 的动态导入。不要在着色器调用 onReady 前隐藏回退内容;如果 WebGPU 初始化失败,页面仍必须清晰可读且内容完整。

分层规则

  • 为媒体包装器设置 position: relative、明确的尺寸、overflow: hidden 和 isolation: isolate。
  • 将回退内容的 z-index 设为 0,将 canvas 的 z-index 设为 1。
  • 使用 position: absolute; inset: 0; width: 100%; height: 100% 填满包装器。
  • 为着色器图层设置 pointer-events: none;Shaders 会全局监听指针,并使用 canvas 边界转换指针坐标。
  • 将着色器包装器标记为 aria-hidden="true";由回退图像提供无障碍名称。
  • 将文案、链接和控件放在 canvas 上方,确保效果不会拦截交互。
  • 确保回退内容与 ImageTexture 使用相同的裁剪方式。对于满幅媒体,请使用 objectFit="cover"。

移除失效的聚光灯模式

删除旧实现,不要将其隐藏:

  • 第二张揭示图片;
  • 径向 mask-image 和自定义揭示变量;
  • 与指针位置相关的烟雾或模糊叠加层;
  • 组件本地的 requestAnimationFrame 指针缓动;
  • 仅为手电筒效果添加的 pointerenter、pointermove、pointerleave 和尺寸调整记录逻辑;
  • 引用已弃用揭示层的粗略指针规则。

同时保留两套系统会导致坐标漂移、增加 GPU 负载,并使回退行为变得混乱。

性能与动态效果

  • 仅在 WebGPU 检查通过后,延迟加载着色器模块。
  • 媒体面板中只保留一个着色器画布。
  • 使用库的 onReady 回调实现短暂的不透明度切换。
  • 不需要遥测时使用 disableTelemetry。
  • 不要为画布尺寸添加动画;如需视差效果,应为稳定的父级元素添加动画。
  • 在 prefers-reduced-motion: reduce 时禁用或卸载着色器。
  • 确保触控布局在使用静态图片时仍可用;不要将关键信息放在效果内部。

验证

运行项目的 lint、生产构建、渲染测试和 git diff --check。然后在真实浏览器中验证:

  1. 确认恰好存在一个 canvas[data-renderer="shaders"]。
  2. 确认着色器进入就绪类,且回退图片仍然存在。
  3. 在媒体区域的多个位置扫动指针。扭曲效果必须沿指针路径移动,不得出现脱离的圆圈。
  4. 确认链接和控件仍可点击。
  5. 确认没有控制台错误或警告。
  6. 确认 WebGPU 不可用或启用减少动态效果时,静态图片仍然显示。
  7. 确认旧的 data-reveal-hover 或径向遮罩层不存在。
  8. 画布初始化后,检查移动端和桌面端的裁切效果。

故障诊断

  • **画布存在但内容空白:**确认包装元素的尺寸非零,且图片 URL 同源或可通过 CORS 读取。
  • **图片已渲染但没有波纹:**将 CursorRipples 保留在 ImageTexture 之后;它需要子元素/输入表面。
  • **波纹位置偏移:**移除手动指针变换,并检查经过变换的祖先元素是否改变了画布边界。
  • **页面在 SSR 期间崩溃:**将着色器移入仅客户端运行的延迟加载组件。
  • **图片加载时闪烁:**保留回退图片,并且仅通过 onReady 淡入着色器。
  • **初始包体积变大:**确认 Shaders 导入仅位于延迟加载模块中。
  • **效果挡住按钮:**确保画布对指针事件透明,并将控件放在更高的堆叠层级。

交接

报告受影响的媒体、Shaders 包版本、回退行为、减少动态效果时的行为、构建/测试结果,以及实时交互验证情况。明确区分本地已就绪的效果与已发布的部署。

评论

支持 Markdown