关于 shaders-cursor-ripples
shaders-cursor-ripples 是一套将 CursorRipples 着色器效果应用于页面图像的开发技能,面向在现有网页中实现指针驱动图像扭曲的开发者。它强调懒加载、静态图像回退、WebGPU 检查和减少动态效果支持。
主要功能
- 01在图像上应用指针涟漪扭曲
- 02支持 React、Vue、Svelte 和 Solid
- 03懒加载着色器模块
- 04保留可访问的静态图像回退
- 05处理 WebGPU 与减少动态效果
适用场景
- 01为页面媒体添加指针交互扭曲
- 02在 WebGPU 不可用时保留图像显示
- 03替换旧的聚光灯式图像揭示效果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ boraoztunc/ skills --skill shaders-cursor-ripples安装后在 Claude Code 中输入/shaders-cursor-ripples确认已加载。
附带文件REFERENCES.md
详细介绍
Shaders 游标涟漪
核心约定
- 保留现有页面、内容和语义图像。
- 安装
shaders,并从当前框架的子路径导入。 - 通过一个
Shader画布渲染源图像。 - 将
CursorRipples放在ImageTexture之后,使其对该图像进行后期处理。 - 在根元素上保留
toneMapping="aces"。 - 让 Shaders 跟踪游标。移除自定义聚光坐标、径向蒙版、重复的揭示图像和指针动画循环。
- 在画布下方保留一张真实图像,作为无障碍加载内容和 WebGPU 回退。
- 在减少动态效果或不支持 WebGPU 时禁用着色器。
- 延迟加载着色器代码,避免增大页面的初始打包体积。
当用户只要求着色器效果时,不要照搬参考作品中的丝带、斑块、辉光、排版、布局、文案、颜色或标识。不要用 Shaders 的 Water 组件替代:CursorRipples 才是交互式图像位移效果。
编辑前检查
- 找到真实的媒体容器、图像 URL、裁剪方式、叠加层、z-index 和现有动态效果。
- 确认容器渲染后的宽度和高度均非零。
- 搜索旧的揭示代码,例如
data-reveal-hover、mask-image: radial-gradient、重复图像、requestAnimationFrame和手动指针监听器。 - 保留无关的视差或入场动态效果,除非它们与着色器画布冲突。
- 如果软件包可能已变更,请检查已安装的
shaders版本和当前框架 API。
安装
npm install shaders
从 shaders/react、shaders/vue、shaders/svelte 或 shaders/solid 导入。对于 Vite 项目,绝不要将 shaders 添加到 optimizeDeps.exclude;其 CommonJS 依赖需要 Vite 预打包。通常无需添加 optimizeDeps 配置项。
这是一个付费的非 OSS 依赖。 shaders 软件包附带专有的
“Shader Effects License Agreement”,且 npm 显示 license: None——只有付费后
才能获得授权。它不是 MIT/Apache 许可证,不能视为免费的传递依赖。任何商业发布前
都必须确认许可;如果项目无法引入付费依赖,应优先选择
webgl-laser 或手动编写着色器。
必需的组件组合
保留以下组件顺序和值:
<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,将画布的 z-index 设为1。 - 使用
position: absolute; inset: 0; width: 100%; height: 100%填满容器。 - 将着色器图层设为
pointer-events: none;Shaders 会进行全局监听,并使用画布边界换算指针坐标。 - 将着色器容器标记为
aria-hidden="true";无障碍名称由回退图像提供。 - 将文案、链接和控件置于画布上方,确保效果不会拦截交互。
- 保持回退内容与
ImageTexture使用相同的裁剪方式。对于全幅媒体,使用objectFit="cover"。
移除失效的聚光灯模式
删除旧实现,不要将其隐藏:
- 第二张揭示图片;
- 径向
mask-image和自定义揭示变量; - 与指针位置相关的烟雾或模糊叠加层;
- 组件本地的
requestAnimationFrame指针缓动; - 仅为手电筒效果添加的
pointerenter、pointermove、pointerleave和尺寸调整记录逻辑; - 引用已弃用揭示层的粗略指针规则。
同时保留两套系统会导致坐标漂移、增加 GPU 负载,并使回退行为变得混乱。
性能与动态效果
- 仅在 WebGPU 检查通过后,延迟加载着色器模块。
- 媒体面板中只保留一个着色器画布。
- 使用库的
onReady回调实现短暂的不透明度切换。 - 不需要遥测时使用
disableTelemetry。 - 不要为画布尺寸添加动画;如需视差效果,应为稳定的父级元素添加动画。
- 在
prefers-reduced-motion: reduce时禁用或卸载着色器。 - 确保触控布局在使用静态图片时仍可用;不要将关键信息放在效果内部。
验证
运行项目的 lint、生产构建、渲染测试和 git diff --check。然后在真实浏览器中验证:
- 确认恰好存在一个
canvas[data-renderer="shaders"]。 - 确认着色器进入就绪类,且回退图片仍然存在。
- 在媒体区域的多个位置扫动指针。扭曲效果必须沿指针路径移动,不得出现脱离的圆圈。
- 确认链接和控件仍可点击。
- 确认没有控制台错误或警告。
- 确认 WebGPU 不可用或启用减少动态效果时,静态图片仍然显示。
- 确认旧的
data-reveal-hover或径向遮罩层不存在。 - 画布初始化后,检查移动端和桌面端的裁切效果。
故障诊断
- **画布存在但内容空白:**确认包装元素的尺寸非零,且图片 URL 同源或可通过 CORS 读取。
- **图片已渲染但没有波纹:**将
CursorRipples保留在ImageTexture之后;它需要子元素/输入表面。 - **波纹位置偏移:**移除手动指针变换,并检查经过变换的祖先元素是否改变了画布边界。
- **页面在 SSR 期间崩溃:**将着色器移入仅客户端运行的延迟加载组件。
- **图片加载时闪烁:**保留回退图片,并且仅通过
onReady淡入着色器。 - **初始包体积变大:**确认 Shaders 导入仅位于延迟加载模块中。
- **效果挡住按钮:**确保画布对指针事件透明,并将控件放在更高的堆叠层级。
交接
报告受影响的媒体、Shaders 包版本、回退行为、减少动态效果时的行为、构建/测试结果,以及实时交互验证情况。明确区分本地已就绪的效果与已发布的部署。