[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-95009":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":12,"contributorsCount":12,"subscribersCount":12,"size":12,"stars1d":12,"stars7d":14,"stars30d":14,"stars90d":12,"forks30d":12,"starsTrendScore":12,"compositeScore":15,"rankGlobal":9,"rankLanguage":9,"license":16,"archived":17,"fork":17,"defaultBranch":18,"hasWiki":19,"hasPages":17,"topics":20,"createdAt":9,"pushedAt":9,"updatedAt":21,"readmeContent":22,"aiSummary":23,"trendingCount":12,"starSnapshotCount":12,"syncStatus":24,"lastSyncTime":25,"discoverSource":26},95009,"svg_animate","Treamz\u002Fsvg_animate","Treamz","Plays SVGs that declare their own animation (SMIL or CSS keyframes) on top of the vector_graphics renderer that flutter_svg uses.",null,"Dart",118,0,103,15,49,"Other",false,"main",true,[],"2026-08-24 04:01:23","# svg_animate\n\n[![pub package](https:\u002F\u002Fimg.shields.io\u002Fpub\u002Fv\u002Fsvg_animate.svg)](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fsvg_animate)\n[![pub points](https:\u002F\u002Fimg.shields.io\u002Fpub\u002Fpoints\u002Fsvg_animate)](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fsvg_animate\u002Fscore)\n[![license](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-BSD--3--Clause-blue)](LICENSE)\n[![Flutter](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FFlutter-%3E%3D3.38-blue)](https:\u002F\u002Fflutter.dev)\n[![platform](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatform-android%20%7C%20ios%20%7C%20macos%20%7C%20windows%20%7C%20linux%20%7C%20web-lightgrey)](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fsvg_animate)\n\nPlays SVGs that declare their own animation — SMIL (`\u003Canimate>`,\n`\u003CanimateTransform>`, `\u003CanimateMotion>`, `\u003Cset>`), CSS `@keyframes`, and CSS\nmotion paths — using the same `vector_graphics` renderer that\n[`flutter_svg`](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fflutter_svg) draws still SVGs with.\n\n\u003C!-- markdownlint-disable MD033 -->\n\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002FTreamz\u002Fsvg_animate\u002Fmain\u002Fdoc\u002Fdemo.svg\"\n     width=\"440\" alt=\"Four animated SVGs: a rotating spinner, a pulsing ring, a progress bar, and a marker following a path\">\n\u003C!-- markdownlint-enable MD033 -->\n\n*The image above is a single SVG file, animating in your browser exactly as it\ndoes in Flutter through this package. Its source is\n[`doc\u002Fdemo.svg`](doc\u002Fdemo.svg).*\n\n`AnimatedSvgPicture` is a drop-in companion to `SvgPicture`: it takes the same\narguments for sizing, alignment, theming, color filtering, semantics and error\nhandling, and reuses `flutter_svg`'s `SvgTheme`, `ColorMapper` and\n`DefaultSvgTheme`. An SVG with no animation renders exactly as `SvgPicture`\nrenders it, and starts no ticker.\n\n```dart\nAnimatedSvgPicture.asset('assets\u002Fspinner.svg', width: 48, height: 48)\n```\n\nFiles exported by animation editors work as they come. SVGator, the most common\nof them, expresses every movement as a CSS motion path and places repeated\nartwork through `\u003Cuse>`; both are handled, including exports that embed their\nartwork as raster images. See [what is not supported](#what-is-not-supported)\nfor the parts of such files that do not survive.\n\n## Getting started\n\n```yaml\ndependencies:\n  svg_animate: ^0.3.2\n```\n\nThere are constructors for every source `flutter_svg` supports:\n\n```dart\nAnimatedSvgPicture.asset('assets\u002Fspinner.svg');\nAnimatedSvgPicture.network('https:\u002F\u002Fexample.com\u002Fspinner.svg');\nAnimatedSvgPicture.file(File(path));\nAnimatedSvgPicture.memory(bytes);\nAnimatedSvgPicture.string(markup);\n```\n\n## Playback\n\nBy default the animation starts as soon as it loads, and **the SVG decides\nwhether it repeats**: markup that asks to loop forever does, and markup whose\nanimations all end plays once and holds its final frame. Pass `repeat` to\noverride that.\n\n```dart\nAnimatedSvgPicture.asset(\n  'assets\u002Fprogress.svg',\n  repeat: false,\n  onCompleted: () => debugPrint('done'),\n);\n```\n\nFor play\u002Fpause\u002Fseek, pass an `AnimatedSvgController`. It can be used before the\npicture has loaded — requests are remembered and applied once it is ready.\n\n```dart\nfinal controller = AnimatedSvgController();\n\nAnimatedSvgPicture.asset(\n  'assets\u002Fspinner.svg',\n  controller: controller,\n  autoPlay: false,\n);\n\ncontroller.play();\ncontroller.pause();\ncontroller.seek(0.5);                                  \u002F\u002F 0.0 to 1.0\ncontroller.seekTo(const Duration(milliseconds: 500));\n```\n\n`controller.progress` is a stable `Animation\u003Cdouble>`, so it can be handed to an\n`AnimatedBuilder` to follow playback frame by frame, even before loading\nfinishes.\n\n## Supported SVG features\n\n### Animation\n\n| | |\n|---|---|\n| `\u003Canimate>` | `values` \u002F `keyTimes` \u002F `keySplines`, `from` \u002F `to` \u002F `by` |\n| `\u003CanimateTransform>` | `translate`, `scale`, `rotate`, `skewX`, `skewY` |\n| `\u003CanimateMotion>` | `path` and `\u003Cmpath>`, `rotate=\"auto\"` \u002F `auto-reverse` |\n| `\u003Cset>` | yes |\n| `calcMode` | `linear`, `discrete`, `paced`, `spline` |\n| Timing | `begin` (offsets), `dur`, `end`, `repeatCount`, `repeatDur`, `fill` |\n| Composition | `additive=\"sum\"`, `accumulate=\"sum\"` |\n| Targeting | `href` \u002F `xlink:href`, or the parent element |\n| CSS `@keyframes` | `animation` shorthand and every longhand, per-keyframe `animation-timing-function` |\n| `animation-direction` | `normal`, `reverse`, `alternate`, `alternate-reverse` |\n| `animation-fill-mode` | `forwards` and `both` hold the last frame |\n| CSS motion paths | `offset-path: path(...)`, `offset-distance`, `offset-rotate` |\n| `transform-origin` | resolved against the view box |\n| Animated value types | numbers, lengths, percentages, colors (hex, `rgb()`, `hsl()`, SVG keywords), number lists, transform lists |\n\n### Drawing\n\nEverything is drawn by `vector_graphics`, so an animated SVG supports exactly\nwhat a still one does through `flutter_svg`: paths and shapes, linear and radial\ngradients, patterns, `clipPath`, `mask`, text, embedded raster images, and the\nfifteen CSS blend modes.\n\nTwo things that a still SVG does *not* get are handled here, because the\nrenderer cannot do them on its own:\n\n- **CSS in a `\u003Cstyle>` element** is resolved into presentation attributes. The\n  `vector_graphics` compiler implements no CSS selectors, so without this a\n  stylesheet-driven SVG renders unstyled. `SvgPicture` ignores `\u003Cstyle>`\n  entirely.\n- **A `\u003Cuse>` pointing at an `\u003Cimage>`** is expanded into the image. The\n  renderer loses an image's size through a reference and then fails the whole\n  picture rather than that one element.\n\n### What is not supported\n\n| | why |\n|---|---|\n| `\u003Cfilter>` and everything in it | `vector_graphics` drops filters; the element still draws, without the effect |\n| `mix-blend-mode: plus-lighter` | not among the fifteen modes the renderer knows; editors reach for it to make a glow |\n| Morphing the `d` attribute | those animations switch between values instead of interpolating |\n| `begin` on an event or another animation | there is no interactive document to fire it |\n| CSS pseudo-classes such as `:hover` | same |\n| CSS custom properties and `var()` | left alone, so the element keeps the presentation attribute it already had |\n| `\u003Cscript>` | not run |\n| `@media`, `@supports` | skipped rather than guessed at |\n\n## How it compares\n\nThis package deliberately covers less of SVG than the alternatives, and carries\nmuch less with it.\n\n- It renders through `vector_graphics`, the same renderer `flutter_svg` uses, so\n  animated and still SVGs in one app are drawn by the same code and share\n  `SvgTheme` and `ColorMapper`.\n- It adds two pure Dart packages, `xml` and `path_parsing`, both already in\n  `flutter_svg`'s own dependency tree. No JavaScript runtime, no native engine,\n  no FFI.\n- A frame costs what a still SVG costs to draw, because frames are compiled\n  ahead of time rather than evaluated as they are shown.\n\nWhich to reach for:\n\n| | |\n|---|---|\n| **svg_animate** | Spinners, loaders, animated icons, exports from animation editors. You already use `flutter_svg` and want to keep the dependency list short. |\n| [**full_svg_flutter**](https:\u002F\u002Fpub.dev\u002Fpackages\u002Ffull_svg_flutter) | You need filters, `d` morphing, or SVGs that carry `\u003Cscript>`. It covers considerably more of the format, and bundles a QuickJS runtime and `woff2` to do it. |\n| [**anim_svg**](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fanim_svg) | You would rather transpile to Lottie and render through the native thorvg engine. |\n| [**flutter_svg**](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fflutter_svg) | The SVG does not animate. |\n| [**lottie**](https:\u002F\u002Fpub.dev\u002Fpackages\u002Flottie), [**rive**](https:\u002F\u002Fpub.dev\u002Fpackages\u002Frive) | The animation is authored in those formats to begin with. Both are far more capable than any SVG animation runtime, if you can choose the format. |\n\nWhat is written above about other packages comes from their descriptions and\ndependency lists, not from benchmarking them.\n\n## How it works, and what it costs\n\nWhen the picture loads, the animations the document declares are resolved, and\nthe document is sampled to a static SVG at each frame time. Each sample is\ncompiled by `vector_graphics_compiler` — the same compiler `flutter_svg` uses —\nin a background isolate. Playback then swaps between those pre-compiled frames,\nso drawing one costs the same as drawing a still SVG.\n\nThe trade-off is loading: compiling *N* frames takes roughly *N* times as long\nas loading a still SVG, and the frames stay in memory while they are cached.\n\nThe awkward case is an SVG that embeds raster images, because the image data\nappears in every compiled frame and is far larger than the drawing around it.\nTwo things keep that affordable. The run of bytes every frame begins with, which\nis where the encoder puts whatever a picture embeds, is stored once instead of\nper frame. And an embedded image is decoded once for the whole animation instead\nof on every frame change. For a 450×450 banner carrying five embedded bitmaps\nthat is 5.1 MB rather than 27.5 MB, and 1.5 ms rather than 6.8 ms to change\nframe — the same cost as an SVG that embeds nothing at all.\n\nAn animation can say what it costs rather than being guessed at:\n\n```dart\nfinal AnimatedSvgFrames frames = await compileAnimatedSvg(markup);\ndebugPrint('${frames.frameCount} frames, ${frames.compiledByteSize} bytes');\n```\n\n- `frameRate` (default `60`) — frames compiled per second of animation.\n- `maxFrames` (default `300`) — ceiling; longer animations are sampled at a\n  lower rate rather than growing without bound.\n- `placeholderBuilder` — shown while the animation compiles.\n- `svgAnimateCache` — the shared cache of compiled animations. Lower its\n  `maximumSize` (default 10) to trade recompilation for memory.\n\nOn the web there are no isolates, so compilation runs on the main thread; prefer\na lower `frameRate` for long animations there.\n\n## Contributing\n\nDevelopment setup and the release process are in\n[CONTRIBUTING.md](CONTRIBUTING.md). Releases are cut by pushing a `v0.0.0` tag;\nGitHub Actions verifies the tagged commit and publishes it.\n\n## License\n\nBSD 3-Clause. Portions are derived from the Flutter project, which is\ndistributed under the same license.\n","这是一个为 Flutter 应用提供原生 SVG 动画支持的 Dart 插件，可直接播放内嵌 SMIL（如 \u003Canimate>、\u003CanimateMotion>）或 CSS @keyframes \u002F motion path 声明的动画 SVG 文件。它复用 flutter_svg 的 vector_graphics 渲染器，确保静态渲染一致性，并支持 asset、network、file 等多种加载方式及 play\u002Fpause\u002Fseek 控制。适用于需要轻量级、声明式矢量动画的跨平台 Flutter 应用场景，如加载指示器、交互动画图标、数据可视化元素等，无需额外 Canvas 绘制或 GIF 替代方案。",2,"2026-08-19 02:30:10","CREATED_QUERY"]