Add cursor-following fluid WebGPU distortion over an existing image with the Shaders library's ImageTexture and CursorRipples components. Use when a hero, galle
复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-shaders-cursor-ripples-d9c80a9b946f ,按照其中的说明把「shaders-cursor-ripples」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
shaders and import from the active framework subpath.Shader canvas.CursorRipples after ImageTexture so it post-processes that image.toneMapping="aces" on the root.When the user asks for only the shader effect, do not copy a reference's ribbon, blob, glow, typography, layout, copy, colors, or identity. Do not substitute the Shaders Water component: CursorRipples is the interactive image-displacement effect.
data-reveal-hover, mask-image: radial-gradient, duplicated images, requestAnimationFrame, and manual pointer listeners.shaders version and current framework API when the package may have changed.npm install shaders
Import from shaders/react, shaders/vue, shaders/svelte, or shaders/solid. For Vite projects, never add shaders to optimizeDeps.exclude; its CommonJS dependencies need Vite pre-bundling. No optimizeDeps entry is normally required.
Before a commercial release, verify the current Shaders license terms.
Keep the component order and values below:
<Shader toneMapping="aces">
<ImageTexture url={imageUrl} objectFit="cover" />
<CursorRipples decay={7.3} radius={0.6} />
</Shader>
Use this as the baseline before tuning intensity, chromaticSplit, or edges. Do not add SolidColor, Blob, Form3D, GaborNoise, Glow, or another generator unless the user explicitly requests the reference's generated artwork.
For React, copy and adapt assets/react/cursor-ripple-shader.tsx and assets/react/cursor-ripple-media.css.
Mount the shader only after the browser confirms WebGPU and motion is allowed:
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);
}, []);
Keep the semantic image in the wrapper, then overlay the lazy shader:
<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>
For Next.js, an ssr: false dynamic import is also valid. Do not hide the fallback until the shader calls onReady; a failed WebGPU initialization must leave the page legible and complete.
position: relative, a definite size, overflow: hidden, and isolation: isolate.0 and the canvas at z-index 1.position: absolute; inset: 0; width: 100%; height: 100%.pointer-events: none; Shaders listens globally and converts pointer coordinates using the canvas bounds.aria-hidden="true"; the fallback image owns the accessible name.ImageTexture. Use objectFit="cover" for full-bleed media.Delete the old implementation rather than leaving it hidden:
mask-image and custom reveal variables;requestAnimationFrame pointer easing;pointerenter, pointermove, pointerleave, and resize bookkeeping created only for the flashlight;Keeping both systems causes coordinate drift, extra GPU work, and confusing fallbacks.
onReady callback for a short opacity handoff.disableTelemetry when telemetry is not required.prefers-reduced-motion: reduce.Run the project's lint, production build, rendered tests, and git diff --check. Then verify in a real browser:
canvas[data-renderer="shaders"] exists.data-reveal-hover or radial-mask layer is absent.CursorRipples after ImageTexture; it requires a child/input surface.onReady.Report the affected media, Shaders package version, fallback behavior, reduced-motion behavior, build/test results, and live interaction verification. Distinguish a locally ready effect from a published deployment.