{"id":51241390,"url":"https://github.com/blazejkustra/react-native-morph-view","last_synced_at":"2026-06-29T00:32:22.583Z","repository":{"id":361577378,"uuid":"1254993332","full_name":"blazejkustra/react-native-morph-view","owner":"blazejkustra","description":"Morph one image into another with a smooth gooey effect.","archived":false,"fork":false,"pushed_at":"2026-06-28T10:52:50.000Z","size":2999,"stargazers_count":114,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-28T12:10:16.977Z","etag":null,"topics":["expo","morph","react-native","shaders"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/react-native-morph-view","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blazejkustra.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-31T09:03:00.000Z","updated_at":"2026-06-28T10:52:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/blazejkustra/react-native-morph-view","commit_stats":null,"previous_names":["blazejkustra/react-native-morph-view"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/blazejkustra/react-native-morph-view","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blazejkustra%2Freact-native-morph-view","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blazejkustra%2Freact-native-morph-view/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blazejkustra%2Freact-native-morph-view/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blazejkustra%2Freact-native-morph-view/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blazejkustra","download_url":"https://codeload.github.com/blazejkustra/react-native-morph-view/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blazejkustra%2Freact-native-morph-view/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34909137,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expo","morph","react-native","shaders"],"created_at":"2026-06-29T00:32:21.867Z","updated_at":"2026-06-29T00:32:22.575Z","avatar_url":"https://github.com/blazejkustra.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-native-morph-view\n\nhttps://github.com/user-attachments/assets/4d66f6e4-369d-44ca-bf58-e3152bc87e5c\n\nA React Native view that smoothly morphs one image into another. Flip a single `toggle` prop and the two shapes blend together with a native shader for a fluid, gooey transition.\n\n- **Real gooey morph on both platforms** — a blur + alpha-threshold shader (Metal on iOS, AGSL on Android) fuses the two silhouettes instead of crossfading them\n- **One prop drives everything** — flip `toggle` and the view animates from `from` to `to` and back; no imperative animation code\n- **Works with any image** — bundled assets (`require(...)`), remote URLs, or file URIs, via the familiar React Native image source shape\n- **Gooey outline** — an optional border traces the morphing silhouette, not a rectangular CSS box around the view\n- **Tunable goop** — `blurRadius` controls how molten the midpoint looks, `duration` controls the timing\n- **One API, three platforms** — iOS, Android, and Web share the same `\u003cMorphView /\u003e`; web gets an animated crossfade fallback\n- **Fabric / New Architecture only**\n\n## Installation\n\n```sh\nnpm install react-native-morph-view\n```\n\n### Requirements\n\n- React Native 0.76+ (New Architecture / Fabric)\n- iOS 15.1+\n- Android API 33+ (AGSL runtime shaders require Android 13+; older devices fall back to a crossfade)\n\n### Web setup\n\nOn web, `MorphView` resolves image sources through `Image.resolveAssetSource`, which React Native Web doesn't provide. If you target web, polyfill it before rendering: https://github.com/necolas/react-native-web/pull/2814\n\n## Usage\n\nRender a `MorphView`, give it two images, and flip `toggle` to play the morph:\n\n```tsx\nimport { useState } from 'react';\nimport { MorphView } from 'react-native-morph-view';\n\nexport default function App() {\n  const [on, setOn] = useState(false);\n\n  return (\n    \u003cMorphView\n      toggle={on}\n      from={require('./assets/heart.png')}\n      to={require('./assets/star.png')}\n      blurRadius={24}\n      tintColor=\"#FF3B6B\"\n      style={{ width: 200, height: 200 }}\n      onTouchEnd={() =\u003e setOn((v) =\u003e !v)}\n    /\u003e\n  );\n}\n```\n\n`MorphView` extends `ViewProps`, so layout, `style`, touch handlers, and accessibility props all work as usual. Use a remote or file image anywhere you'd use a bundled one:\n\n```tsx\n\u003cMorphView\n  toggle={on}\n  from={require('./assets/coffee.png')}\n  to={{ uri: 'https://example.com/battery.png' }}\n  style={{ width: 160, height: 160 }}\n/\u003e\n```\n\n## API\n\n### `\u003cMorphView\u003e`\n\nRenders both images and animates the gooey morph between them whenever `toggle` changes.\n\n| Prop           | Type               | Default | Description                                                                                                                                             |\n| -------------- | ------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `toggle`       | `boolean`          | —       | Which image is shown. `false` → `from`, `true` → `to`. Flipping it plays the morph in that direction. **Required.**                                    |\n| `from`         | `MorphImageSource` | —       | Image shown while `toggle` is `false`. `require(...)`, `{ uri }`, or a file URI. **Required.**                                                         |\n| `to`           | `MorphImageSource` | —       | Image shown while `toggle` is `true`. **Required.**                                                                                                    |\n| `blurRadius`   | `number`           | `24`    | Peak blur applied at the midpoint of the morph (points/dp). Larger = goopier.                                                                          |\n| `duration`     | `number`           | `600`   | Morph duration in milliseconds.                                                                                                                        |\n| `tintColor`    | `ColorValue`       | —       | Optional template tint applied to both images — recolors opaque pixels, mimicking the SF-Symbol look. Omit to keep each image's own colors.            |\n| `borderColor`  | `ColorValue`       | —       | Color of the gooey outline that hugs the morphing silhouette. Drawn only when `borderColor` is set **and** `borderWidth` is greater than 0.            |\n| `borderWidth`  | `number`           | `0`     | Thickness of the gooey outline in points. `0` disables it.                                                                                             |\n| `...ViewProps` | `ViewProps`        | —       | All standard `View` props — `style`, `onTouchEnd`, `accessibilityLabel`, etc.                                                                          |\n\n### `MorphImageSource`\n\n```ts\ntype MorphImageSource = number | { uri: string };\n```\n\nA bundled asset (`require('./x.png')` resolves to a `number`) or a remote / file image (`{ uri: 'https://…' }`).\n\n## How it works\n\nBoth images are rendered natively, then blended through an alpha-threshold shader. As `toggle` flips, each image's blur ramps up toward `blurRadius` at the midpoint and back down, while the threshold step re-sharpens the combined alpha — so overlapping blurred regions fuse into a single connected blob (the \"metaball\" effect) before resolving into the target shape.\n\n- **iOS** runs the effect as a Metal shader.\n- **Android** runs it as an AGSL `RuntimeShader` (Android 13+).\n- **Web** can't run the native shader, so it approximates the morph with an ease-in-out crossfade plus a static soft blur on each image. No metaball fusing — for that, run on iOS or Android.\n\n## Tips\n\n- For the cleanest goo, use images with transparent backgrounds and solid, opaque shapes — the shader works on the alpha channel.\n- Pair `MorphView` with `LayoutAnimation` if the surrounding layout also changes when you toggle, so the whole transition stays in sync.\n- Increase `blurRadius` for blobbier, more liquid transitions; decrease it for a tighter, snappier morph.\n- Use `tintColor` to drive monochrome glyphs from your theme without shipping pre-colored assets.\n\n## Examples\n\nA runnable demo lives in [`example/`](./example) — an Expo app that morphs between shapes, photos, and a multi-image gallery, with live controls for `blurRadius`, `duration`, `tintColor`, and the gooey border.\n\n```sh\nyarn install\nyarn example ios      # or: yarn example android / yarn example web\n```\n\n```tsx\n// Morph through any-length list of images\nconst GALLERY = [\n  require('./assets/blob.png'),\n  require('./assets/star.png'),\n  require('./assets/expo.png'),\n];\n\n// Gooey outline + template tint\n\u003cMorphView\n  toggle={on}\n  from={GALLERY[0]}\n  to={GALLERY[1]}\n  tintColor=\"#0A84FF\"\n  borderColor=\"#0A84FF\"\n  borderWidth={3}\n  blurRadius={32}\n  style={{ width: 200, height: 200 }}\n/\u003e;\n```\n\n## Contributing\n\n- [Development workflow](CONTRIBUTING.md#development-workflow)\n- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)\n- [Code of conduct](CODE_OF_CONDUCT.md)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblazejkustra%2Freact-native-morph-view","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblazejkustra%2Freact-native-morph-view","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblazejkustra%2Freact-native-morph-view/lists"}