flutter_svg 0.5.1

  • README.md
  • CHANGELOG.md
  • Example
  • Installing
  • Versions
  • 96

flutter_svg

Pub Build Status Coverage Status

Flutter Logo which can be rendered by this package!

Draw SVG and Android VectorDrawable (XML) files on a Flutter Widget.

Getting Started

This is a Dart-native rendering library. Issues/PRs will be raised in Flutter and flutter/engine as necessary for features that are not good candidates for Dart implementations (especially if they're impossible to implement without engine support). However, not everything that Skia can easily do needs to be done by Skia; for example, the Path parsing logic here isn't much slower than doing it in native, and Skia isn't always doing low level GPU accelerated work where you might think it is (e.g. Dash Paths).

All of the SVGs in the assets/ folder (except the text related one(s)) now have corresponding PNGs in the golden/ folder that were rendered using flutter test tool/gen_golden.dart and compared against their rendering output in Chrome. Automated tests will continue to compare these to ensure code changes do not break known-good renderings.

Basic usage (to create an SVG rendering widget from an asset):

final String assetName = 'assets/image.svg';
final Widget svg = new SvgPicture.asset(
  assetName,
);

You can color/tint the image like so:

final String assetName = 'assets/icon.svg';
final Widget svgIcon = new SvgPicture.asset(
  assetName,
  color: Colors.red,
);

The default placeholder is an empty box (LimitedBox) - although if a height or width is specified on the SvgPicture, a SizedBox will be used instead (which ensures better layout experience). There is currently no way to show an Error visually, however errors will get properly logged to the console in debug mode.

You can also specify a placeholder widget. The placeholder will display during parsing/loading (normally only relevant for network access).

// Will print error messages to the console.
final String assetName = 'assets/image_that_does_not_exist.svg';
final Widget svg = new SvgPicture.asset(
  assetName,
);

final Widget networkSvg = new SvgImage.network(
  'https://site-that-takes-a-while.com/image.svg',
  loadingPlaceholderBuilder: (BuildContext context) => new Container(
      padding: const EdgeInsets.all(30.0),
      child: const CircularProgressIndicator()),
);

If you'd like to render the SVG to some other canvas, you can do something like:

import 'package:flutter_svg/flutter_svg.dart';
final DrawableRoot svgRoot = await svg.loadAsset('assets/image.svg');

// If you only want the final Picture output, just use
final Picture picture = svgRoot.toPicture();

// Otherwise, if you want to draw it to a canvas:
// Optional, but probably normally desirable: scale the canvas dimensions to
// the SVG's viewbox
svgRoot.scaleCanvasToViewBox(canvas);

// Optional, but probably normally desireable: ensure the SVG isn't rendered
// outside of the viewbox bounds
svgRoot.clipCanvasToViewBox(canvas);
svgRoot.draw(canvas, size);

The SvgPicture helps to automate this logic, and it provides some convenience wrappers for getting assets from multiple sources and caching the resultant Picture. It does not render the data to an Image at any point; you certainly can do that in Flutter, but you then lose some of the benefit of having a vector format to begin with.

While I'm making every effort to avoid needlessly changing the API, it's not guarnateed to be stable yet (hence the pre-1.0.0 version). To date, the biggest change is deprecating the SvgImage widgets in favor of SvgPicture - it became very confusing to maintain that name, as Pictures are the underlying mechanism for rendering rather than Images.

See main.dart for a complete sample.

Use Cases

  • Your designer creates a vector asset that you want to include without converting to 5 different raster format resolutions.
  • Your vector drawing is meant to be static and non (or maybe minimally) interactive.
  • You want to load SVGs dynamically from network sources at runtime.
  • You want to paint SVG data and render it to an image.

TODO

This list is not very well ordered. I'm mainly picking up things that seem interesting or useful, or where I've gotten a request to fix something/example of something that's broken.

  • [ ] Text support.
  • [x] Gradient support (Linear: Mostly done, Radial: finishing this will require newer version of flutter).
  • [x] Dash path support.
  • [ ] Dash path with percentage dasharray values.
  • [ ] More SVG samples to cover more complicated cases (getting there - please file issues for things that don't work!).
  • [ ] Display/visibility support.
  • [x] Unit tests. In particular, tests that validate XML -> Drawable* structures. (Vastly improved as of 0.2.) this is getting there, just need to stay on top of it.
  • [ ] Inheritance of inheritable properties (necessary? preprocess? significant progress, still some rough edges, particularly for definitions).
  • [ ] Support for minimal CSS/styles? See also svgcleaner (partial - style attribute mostly supported).
  • [ ] XLink/ref support (necessary? partially supported for gradients).
  • [ ] Glyph support?
  • [ ] Markers.
  • [ ] Filters/effects.
  • [ ] Android Vector Drawable support (PoC implementation so far).
  • [x] Caching of image.
  • [ ] The XML parsing implementation is heavy for what this really needs. I've made efforts to keep the API forward-reading-only compatible to eventually be able to use a SAX/XMLReader streaming style parser.
  • [x] Color swapping/hue shifting/tinting of asset.

Probably out of scope

  • SMIL animations. That just seems crazy. I think it'll be possible to animate the SVG but probably in a more Flutter driven way.
  • Full (any?) CSS support - preprocess your SVGs (perhaps with svgcleaner to get rid of all CSS?)
  • Scripting in SVGs
  • Foreign elements
  • Rendering properties/hints

SVG sample attribution

SVGs in /assets/w3samples pulled from W3 sample files

SVGs in /assets/deborah_ufw provided by @deborah-ufw

SVGs in /assets/simple are pulled from trivial examples or generated to test basic functionality - some of them come directly from the SVG 1.1 spec.

SVGs in /assets/wikimedia are pulled from Wikimedia Commons

Android Drawables in assets/android_vd are pulled from Android Documentation and examples.

The Flutter Logo created based on the Flutter Logo Widget © Google.

The Dart logo is from dartlang.org © Google

Please submit SVGs this can't render properly (e.g. that don't render here the way they do in chrome), as long as they're not using anything "probably out of scope" (above).

CHANGES

0.5.1

  • Consume latest change from path_drawing (fixes exponent validation)

0.5.0

  • Minimum Flutter version is now 0.5.1 (latest beta as of release)
    • Merge in support for Focal Pointed Radial Gradients
    • Use asset directory references in pubspec.yaml
  • Better support for nested <tspan> styles
  • Support for text-anchor attribute
  • Fix <ellipse> parsing bug (ellipses were drawn at half the expected size)
  • Fix <polyline> parsing bug (polylines were incorrectly forced to be closed)

0.4.1

  • Fix bug where widget caused exception in a FittedBox

0.4.0

  • Added width and height properties to SvgPicture
  • Remove deprecated code related to SvgImage
  • Improved reporting of error conditions
    • Unsupported style elements will report an error
    • Unresolvable definitions will report an error
  • Fixed matchesTextDirection
  • Support for text-anchor

0.3.3

  • Fix centering/scaling of canvas when viewBox is not square
  • Improved color parsing

0.3.2

  • Bug fix around caching for tinting/coloring (color was not being properly included in cache keys)

0.3.1

  • Support for tinting/coloring the output
  • Documentation updates

0.3.0

  • This version represents a major rewrite of the widget(s) involved in rendering SVG drawings. This is primarily to support caching and better performance in rendering.
  • New method on DrawableRoot toPicture to create a ui.Picture object from the SVG.
  • Support for caching of Pictures, similar to how framework caches images. This will eventually be configurable, but is not as of this release.

BREAKING CHANGES

  • BREAKING CHANGE: SvgImage, AvdImage, and VectorDrawableImage have been deprecated. They relied on methods that are less efficient than those now surfaced in SvgPicture.
  • BREAKING CHANGE: Size is no longer passed to SvgPicture - its size is determined by parent size.
  • BREAKING CHANGE: clipToViewBox is now called allowDrawingOutsideViewBox. It defaults to false. It should not ordinarily be set to true, as it can allow unexpected memory usage if your vector graphic tries to draw far outside of the viewBox bounds.
  • BREAKING CHANGE: SvgPicture does not support custom ErrorWidgetBuilders at this point in time. However, errors will be properly logged to the console. This is a result of improvements in the loading/caching of drawings.

0.2.0

  • Fix bug(s) in inheritence (better rendering of Ghostscript_Tiger.svg)
  • Support for <clipPath>s
  • Refactoring of how gradients are handled to enable clipPaths
  • Refactor of SVG shape -> path logic

0.1.4

  • Fix bugs in <radialGradient> percentage handling.
  • Add error widget on error.
  • Add ability to specify error/placeholder widgets.
  • Minor improvement on flutter logo SVG (add missing gradient).
  • Improve docs, unit tests.

0.1.3

  • Add more unit tests and rendering tests (!).
  • Add top level flutter_svg.dart.
  • Fix bugs found in transform matrix logic for skewX and skewY.
  • Minor improvements in handling inheritence for PathFillType.
  • Support gradient spread types (TileModes in Flutter).

0.1.2

  • Bump to path_drawing 0.2.3 (fix arc defect).
  • Handle 'none' in dasharray without throwing exception.
  • Better handling of inheritence and 'none' in fill/stroke/dasharray

0.1.1

  • Handle opacity on groups and inherited/blended opacity.
  • Fixes elements that have both opacity and stroke-opacity or fill-opacity.
  • Improvements for inheritence.
  • Fixes related to unspecified fills on shapes.

0.1.0

Bumping minor version due to internal breaking changes and new support. Works on dev channel as of release (Flutter >= 0.3.6).

  • Refactor DrawableRoot to support top level style definition.
  • Support for dash paths.
  • Support for more inherited attributes.
  • Initial support for @style attributes.
  • Support for rgb() color attribute/styles.
  • Change painting order from stroke first, then fill to fill first, then stroke (matches Chrome rendering of assets/simple/style_attr.svg).

0.0.2

Initial text support. Relies on flutter 0.3.6.

0.0.1

Initial release. Relies on pre-released master.

example/main.dart

import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_svg/avd.dart';
import 'package:flutter_svg/flutter_svg.dart';

const List<String> assetNames = const <String>[
  // 'assets/notfound.svg',
  'assets/flutter_logo.svg',
  'assets/dart.svg',
  'assets/simple/clip_path_3.svg',
  'assets/simple/clip_path_2.svg',
  'assets/simple/clip_path.svg',
  'assets/simple/group_opacity.svg',
  'assets/simple/text.svg',
  'assets/simple/linear_gradient.svg',
  'assets/simple/linear_gradient_2.svg',
  'assets/simple/radial_gradient.svg',
  'assets/simple/rect_rrect.svg',
  'assets/simple/style_attr.svg',
  'assets/w3samples/aa.svg',
  'assets/w3samples/alphachannel.svg',
  'assets/simple/ellipse.svg',
  'assets/simple/dash_path.svg',
  'assets/simple/nested_group.svg',
  'assets/wikimedia/chess_knight.svg',
  'assets/wikimedia/Ghostscript_Tiger.svg',
];

const List<String> iconNames = const <String>[
  'assets/deborah_ufw/new-action-expander.svg',
  'assets/deborah_ufw/new-camera.svg',
  'assets/deborah_ufw/new-gif-button.svg',
  'assets/deborah_ufw/new-gif.svg',
  'assets/deborah_ufw/new-image.svg',
  'assets/deborah_ufw/new-mention.svg',
  'assets/deborah_ufw/new-pause-button.svg',
  'assets/deborah_ufw/new-play-button.svg',
  'assets/deborah_ufw/new-send-circle.svg',
  'assets/deborah_ufw/numeric_25.svg',
];

const List<String> uriNames = const <String>[
  'http://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg',
  'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/410.svg',
  'https://upload.wikimedia.org/wikipedia/commons/b/b4/Chess_ndd45.svg',
];

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter SVG Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<Widget> _painters = <Widget>[];
  double _dimension;

  @override
  void initState() {
    super.initState();
    _dimension = 580.0;

_painters.add(new SvgPicture.string('''<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.1595 3.80852C19.6789 1.35254 16.3807 -4.80966e-07 12.8727 -4.80966e-07C9.36452 -4.80966e-07 6.06642 1.35254 3.58579 3.80852C1.77297 5.60333 0.53896 7.8599 0.0171889 10.3343C-0.0738999 10.7666 0.206109 11.1901 0.64265 11.2803C1.07908 11.3706 1.50711 11.0934 1.5982 10.661C2.05552 8.49195 3.13775 6.51338 4.72783 4.9391C9.21893 0.492838 16.5262 0.492728 21.0173 4.9391C25.5082 9.38548 25.5082 16.6202 21.0173 21.0667C16.5265 25.5132 9.21893 25.5133 4.72805 21.0669C3.17644 19.5307 2.10538 17.6035 1.63081 15.4937C1.53386 15.0627 1.10252 14.7908 0.66697 14.887C0.231645 14.983 -0.0427272 15.4103 0.0542205 15.8413C0.595668 18.2481 1.81686 20.4461 3.5859 22.1976C6.14623 24.7325 9.50955 26 12.8727 26C16.236 26 19.5991 24.7326 22.1595 22.1976C27.2802 17.1277 27.2802 8.87841 22.1595 3.80852Z" fill="black"/>
<path d="M5.50468 7.22599L5.43239 7.19961V2.75006L5.55078 2.75838C6.48068 2.82416 7.05364 3.10795 7.47194 3.31513C7.71834 3.43728 7.91301 3.5337 8.0838 3.5337C8.62293 3.5337 8.90493 2.827 8.90493 2.44821C8.90493 1.93294 8.29428 1.60853 7.78191 1.42707C7.17789 1.2131 6.33963 1.07148 5.53973 1.04817L5.43239 1.0451V0.372776C5.43239 0.188139 5.16763 1.20242e-07 4.90774 1.20242e-07C4.59678 1.20242e-07 4.40421 0.193502 4.40421 0.372776V1.07925L4.30516 1.08954C3.12532 1.21256 0.381048 1.82798 0.381048 4.88C0.381048 7.49544 2.47941 8.2341 4.3307 8.88585L4.40421 8.91179V14.0339L4.28504 14.0247C2.89693 13.917 2.15407 13.2913 1.61174 12.8345C1.31692 12.586 1.084 12.3899 0.863465 12.3899C0.418744 12.3899 1.21448e-07 13.0014 1.21448e-07 13.4754C1.21448e-07 14.4115 1.67331 15.7978 4.29543 15.8398L4.40421 15.8415V16.599C4.40421 16.7781 4.59678 16.9717 4.90774 16.9717C5.16752 16.9717 5.43239 16.7836 5.43239 16.5991V15.791L5.52768 15.7779C7.91611 15.4495 9.28609 13.9149 9.28609 11.5677C9.2862 8.83201 7.41821 7.92283 5.50468 7.22599ZM4.53134 6.88331L4.38177 6.82738C3.23056 6.39726 2.27755 5.93813 2.27755 4.67052C2.27755 3.61972 3.01389 2.97333 4.40709 2.80095L4.53134 2.78563V6.88331ZM5.43604 13.9812L5.30537 14.0052V9.28413L5.45947 9.34958C6.46211 9.775 7.38991 10.366 7.38991 11.7981C7.38991 12.9749 6.69591 13.7502 5.43604 13.9812Z" transform="translate(8.22925 5.12915)" fill="black"/>
</svg>'''));
    _painters.add(new SvgPicture.string('''<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 1000 300"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example tspan01 - using tspan to change visual attributes</desc>

  <g font-family="Verdana" font-size="45" >
    <text x="200" y="150" fill="blue" >
      You are <tspan font-weight="bold" fill="red" >not</tspan> <tspan stroke="green">a</tspan> banana.
    </text>
  </g>

  <!-- Show outline of canvas using 'rect' element -->
  <rect x="1" y="1" width="998" height="298"
        fill="none" stroke="blue" stroke-width="2" />
</svg>'''));
    for (String assetName in assetNames) {
      _painters.add(
        new SvgPicture.asset(assetName),
      );
    }

    for (int i = 0; i < iconNames.length; i++) {
      _painters.add(
        new Directionality(
          textDirection: TextDirection.ltr,
          child: new SvgPicture.asset(
            iconNames[i],
            color: Colors.blueGrey[(i + 1) * 100],
            matchTextDirection: true,
          ),
        ),
      );
    }

    // _painters.add(new SvgPicture.asset(iconNames[0], color: Colors.red));

    for (String uriName in uriNames) {
      _painters.add(
        new SvgPicture.network(
          uriName,
          placeholderBuilder: (BuildContext context) => new Container(
              padding: const EdgeInsets.all(30.0),
              child: const CircularProgressIndicator()),
        ),
      );
    }
    _painters
        .add(new AvdPicture.asset('assets/android_vd/battery_charging.xml'));
  }

  @override
  Widget build(BuildContext context) {
    if (_dimension > MediaQuery.of(context).size.width - 10.0) {
      _dimension = MediaQuery.of(context).size.width - 10.0;
    }
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Column(children: <Widget>[
        new Slider(
            min: 5.0,
            max: MediaQuery.of(context).size.width - 10.0,
            value: _dimension,
            onChanged: (double val) {
              setState(() => _dimension = val);
            }),
        // new FlutterLogo(size: _dimension),
        // new Container(
        //   padding: const EdgeInsets.all(12.0),
        // child:

        // )
        new Expanded(
          child: new GridView.extent(
            shrinkWrap: true,
            maxCrossAxisExtent: _dimension,
            padding: const EdgeInsets.all(4.0),
            mainAxisSpacing: 4.0,
            crossAxisSpacing: 4.0,
            children: _painters.toList(),
          ),
        ),
      ]),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_svg: "^0.5.1"

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter packages get

Alternatively, your editor might support flutter packages get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


      import 'package:flutter_svg/flutter_svg.dart';
  
Version Uploaded Documentation Archive
0.5.1 Jul 2, 2018 Go to the documentation of flutter_svg 0.5.1 Download flutter_svg 0.5.1 archive
0.5.0 Jun 26, 2018 Go to the documentation of flutter_svg 0.5.0 Download flutter_svg 0.5.0 archive
0.4.1 Jun 19, 2018 Go to the documentation of flutter_svg 0.4.1 Download flutter_svg 0.4.1 archive
0.4.0 Jun 18, 2018 Go to the documentation of flutter_svg 0.4.0 Download flutter_svg 0.4.0 archive
0.3.3 Jun 10, 2018 Go to the documentation of flutter_svg 0.3.3 Download flutter_svg 0.3.3 archive
0.3.2 May 29, 2018 Go to the documentation of flutter_svg 0.3.2 Download flutter_svg 0.3.2 archive
0.3.1 May 28, 2018 Go to the documentation of flutter_svg 0.3.1 Download flutter_svg 0.3.1 archive
0.3.0 May 27, 2018 Go to the documentation of flutter_svg 0.3.0 Download flutter_svg 0.3.0 archive
0.2.0 May 20, 2018 Go to the documentation of flutter_svg 0.2.0 Download flutter_svg 0.2.0 archive
0.1.4 May 17, 2018 Go to the documentation of flutter_svg 0.1.4 Download flutter_svg 0.1.4 archive

All 16 versions...

Analysis

We analyzed this package on Jul 13, 2018, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.0.0-dev.63.0
  • pana: 0.11.3
  • Flutter: 0.5.4

Scores

Popularity:
Describes how popular the package is relative to other packages. [more]
92 / 100
Health:
Code health derived from static analysis. [more]
100 / 100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100 / 100
Overall score:
Weighted score of the above. [more]
96
Learn more about scoring.

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Suggestions

  • The description is too short.

    Add more detail about the package, what it does and what is its target use case. Try to write at least 60 characters.

  • Package is pre-v1 release.

    While there is nothing inherently wrong with versions of 0.*.*, it usually means that the author is still experimenting with the general direction API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.19.0 <3.0.0
flutter 0.0.0
meta ^1.1.2 1.1.5
path_drawing ^0.2.4 0.2.4
vector_math ^2.0.4 2.0.6 2.0.7
xml ^3.0.0 3.0.0
Transitive dependencies
collection 1.14.6 1.14.10
matcher 0.12.3
petitparser 1.7.6
sky_engine 0.0.99
stack_trace 1.9.2
typed_data 1.1.5
Dev dependencies
flutter_test
mockito ^2.2.3
path ^1.5.1 1.6.0 1.6.1
test ^0.12.34