[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80317":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":25,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":16,"starSnapshotCount":16,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},80317,"img-fx","Jakubantalik\u002Fimg-fx","Jakubantalik","Animated image generation loader and reveal effect for React  ","http:\u002F\u002Fimage.jakubantalik.com\u002F",null,"TypeScript",111,3,67,1,0,4,17,33,22,1.81,"MIT License",false,"main",true,[],"2026-06-12 02:04:00","# img-fx\n\nAnimated WebGL \"image generation \u002F loader\" effect for React. Wrap any card and it gets a real-time shader-driven loading mosaic that periodically reveals an image from a pool you provide. Ports the canonical `image.html` effect into a small, performant React library.\n\nLive demo: [image.jakubantalik.com](https:\u002F\u002Fimage.jakubantalik.com)\n\n## Install\n\n```bash\nnpm install img-fx\n```\n\n`react`, `react-dom`, and `three` are peer dependencies.\n\n### Local development\n\n```bash\nnpm install\nnpm run dev          # local Vite playground\nnpm run build        # produce dist\u002F (ESM + CJS + .d.ts)\nnpm run build:demo   # produce dist-demo\u002F (static showcase site)\n```\n\n## Quick start\n\n```tsx\nimport { ImageGeneration } from 'img-fx';\n\nexport function Card() {\n  return (\n    \u003CImageGeneration\n      preset=\"pixels-organic\"\n      images={['\u002Fimg\u002Fa.jpg', '\u002Fimg\u002Fb.jpg']}\n      autoReveal\n    >\n      \u003Cdiv className=\"card\" style={{ width: 320, height: 320, borderRadius: 20 }} \u002F>\n    \u003C\u002FImageGeneration>\n  );\n}\n```\n\n## Props\n\n| Prop                | Type                                                                  | Default     | Notes                                                                                            |\n| ------------------- | --------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------ |\n| `preset`            | `'pixels-organic' \\| 'pixels-mechanic'`                               | `'pixels-organic'` | Selects the bundled effect preset (Type × Variant).                                              |\n| `theme`             | `'auto' \\| 'dark' \\| 'light'`                                          | `'auto'`    | `auto` checks `\u003Chtml data-theme>`, `.dark`\u002F`.light` class, inline `color-scheme`, then `prefers-color-scheme`. Live-updates via MutationObserver. |\n| `strength`          | `number` (0..1)                                                       | `1`         | Final opacity multiplier. Doesn't change shader animation.                                       |\n| `cardBg`            | `string` (any CSS colour)                                             | preset      | Override the host card surface colour. Applied verbatim to the wrapper background (alpha preserved) AND parsed to opaque RGB for the shader's `u_cardBg` so colour-proximity logic stays in sync. Accepts hex, `rgb()`\u002F`rgba()`, `hsl()`, named colours, etc. |\n| `images`            | `string \\| string[]`                                                  | `[]`        | Reveal pool. Random pick per cycle, never repeats last.                                          |\n| `autoReveal`        | `boolean`                                                             | `false`     | When true, runs the auto-loop scheduler.                                                         |\n| `revealDelayRange`  | `[number, number]` seconds                                            | `[2, 4]`    | Random shader-only gap between reveals.                                                          |\n| `revealHoldMs`      | `number`                                                              | `2000`      | Image visible duration after reveal animation completes.                                         |\n| `revealFadeOutMs`   | `number`                                                              | `300`       | Cross-fade back to shader.                                                                       |\n| `borderRadius`      | `number`                                                              | (auto)      | Override the corner radius (px). Auto-detected from the wrapped child by default.                |\n| `paused`            | `boolean`                                                             | `false`     | Freezes shader and scheduler.                                                                    |\n| `onCycle`           | `(p) => void`                                                         | -           | Fires on each phase change: `idle` \u002F `reveal` \u002F `visible` \u002F `hide`.                              |\n\n## Manual reveal (ref handle)\n\nPass a ref to trigger reveals from a button click or any other user action,\nwithout enabling `autoReveal`:\n\n```tsx\nimport { useRef } from 'react';\nimport { ImageGeneration, type ImageGenerationHandle } from 'img-fx';\n\nexport function Card() {\n  const ref = useRef\u003CImageGenerationHandle>(null);\n  return (\n    \u003C>\n      \u003CImageGeneration ref={ref} preset=\"pixels-organic\" images={['\u002Fa.jpg', '\u002Fb.jpg']}>\n        \u003Cdiv className=\"card\" style={{ width: 320, height: 320, borderRadius: 20 }} \u002F>\n      \u003C\u002FImageGeneration>\n      \u003Cbutton onClick={() => ref.current?.triggerReveal()}>\n        Reveal image\n      \u003C\u002Fbutton>\n    \u003C\u002F>\n  );\n}\n```\n\n`triggerReveal()` runs one full reveal -> hold -> hide pass and is a no-op\nwhile a reveal is already in progress. Works with or without `autoReveal`.\n\nFor a **Reveal \u002F Hide toggle** button (like the playground on the demo\npage), pair `triggerReveal({ hold: 'manual' })` with `triggerHide()` and\nuse `isImageActive()` to drive the button label:\n\n```tsx\nconst onToggle = () => {\n  const h = ref.current;\n  if (!h) return;\n  if (h.isImageActive()) h.triggerHide();\n  else h.triggerReveal({ hold: 'manual' });\n};\n```\n\n## Scale invariance\n\nCell size, vignette range, and edge-fade are computed in CSS pixels (the shader\ngets `u_dpr` so it can convert from physical pixels back to CSS px). That means\na `pixels-organic` cell stays the same physical size whether the card is 200×200\nor 600×600 — the cell *count* scales with the card, not the cell *size*. No\nchunky pixels on big cards.\n\n## Performance\n\n- Single shared `THREE.WebGLRenderer` for the whole page; one WebGL context.\n- 30 fps cap via rAF accumulator (matches `image.html`).\n- `IntersectionObserver` pauses any card that scrolls offscreen.\n- Strength is implemented as `canvas.style.opacity` — no shader recompile, no uniform reupload.\n- Reveal scratch canvases are reused across frames; only re-allocated when grid size changes.\n- Image bitmaps cached by URL across all card instances.\n\n## License\n\nMIT &copy; Jakub Antalik. See [LICENSE](.\u002FLICENSE).\n","img-fx 是一个用于 React 的动画图像生成加载器和揭示效果库。它利用 WebGL 实时着色器驱动的马赛克加载效果，周期性地从用户提供的图像池中揭示一张图片。该库将经典的 `image.html` 效果封装成一个小型且高性能的 React 组件，支持多种预设样式（如像素有机体和机械风格），并可通过配置项调整主题、强度等参数。适用于需要为卡片组件添加动态视觉效果的场景，比如个人主页、产品展示或任何希望增强用户体验的地方。",2,"2026-06-11 04:00:18","CREATED_QUERY"]