14

The flutter_web docos say to that dart:svg is ported, but how do you use that with the flutter asset / widget system?

hawkbee
  • 1,442
  • 3
  • 18
  • 26
dazza5000
  • 7,075
  • 9
  • 44
  • 89
  • 2
    I dont know how to use dart:svg but I created an example project that uses HtmlElementView to show svg on mobile and on web: https://github.com/masewo/flutter_svg_web_example – masewo Mar 22 '20 at 21:11
  • 1
    Thank you :) flutter_svg it's an option but it only work with android/iOS, websafe_svg also work with web but not work as expect on firefox. – silexcorp Jun 09 '20 at 19:00
  • 1
    It looks like the Firefox issue in websafe_svg has been fixed recently and it should be safe to use it now. https://github.com/peiffer-innovations/websafe_svg/issues/7 – Andrei Aulaska Jan 21 '21 at 02:48

5 Answers5

16

Honestly the best solution I've found is to load the image over a network for the web. Store the asset on a CDN somewhere, get it from the CDN on the web version, and retrieve it from your assets locally on iOS/Android.

I've created a CrossPlatformSvg widget using this library: https://pub.dev/packages/flutter_svg, something like:

class CrossPlatformSvg {
  static Widget asset(
    String assetPath, {
    double width,
    double height,
    BoxFit fit = BoxFit.contain,
    Color color,
    alignment = Alignment.center,
    String semanticsLabel,
  }) {
    // `kIsWeb` is a special Flutter variable that just exists
    // Returns true if we're on web, false for mobile
    if (kIsWeb) {
      return Image.network(
        assetPath,
        width: width,
        height: height,
        fit: fit,
        color: color,
        alignment: alignment,
      );
    } else {
      return SvgPicture.network(
        assetPath,
        width: width,
        height: height,
        fit: fit,
        color: color,
        alignment: alignment,
        placeholderBuilder: (_) => Container(
          width: 30,
          height: 30,
          padding: EdgeInsets.all(30),
          child: CircularIndicator(),
        ),
      );
    }
  }
}

Jack
  • 1,125
  • 1
  • 13
  • 29
  • 5
    It's even works if you place your svg under the assets catalog and call Image.network – atereshkov Nov 17 '20 at 15:18
  • 2
    On the web in debug mode, I get the following error. So I don't think Image.network supports SVG. Tested on 1.26.0-8.0.pre • channel dev The following ImageCodecException was thrown resolving an image codec: Failed to decode image data. – Gpack Feb 26 '21 at 03:44
  • 2
    It seems flutter dropped svg support, see https://github.com/flutter/flutter/issues/74489 – jeiea Apr 01 '21 at 02:11
6

@aterenshkov's approach worked for me (see comments under Jack's answer). Here are the details to implement...

iOS / Android

child: SvgPicture.asset('assets/yourimage.svg')

Web

// remove assets folder reference
child: SvgPicture.asset('yourimage.svg')

Combine these 2 together...

import 'package:flutter/foundation.dart'; // provides kIsWeb property
...
child: kIsWeb ? SvgPicture.asset('yourimage.svg') : SvgPicture.asset('assets/yourimage.svg')
RumbleFish
  • 2,216
  • 1
  • 20
  • 17
5

My Flutter web app would render SVGs in a desktop web browser but not a mobile web browser using flutter_svg. I found it necessary to build with canvaskit support in order for SVGs to render on mobile:

flutter build web --web-renderer canvaskit

However, the docs state that canvaskit adds about 2MB in download size, which was a dealbreaker for me. Sad to say, but I will be using raster images until this is resolved.

jon
  • 3,202
  • 3
  • 23
  • 35
2

flutter_svg version 1.0.0 is out since Dec 2, 2021 including web support. So there is no longer a blocker to use svg images inside a Flutter project.

Timo Bähr
  • 1,826
  • 2
  • 22
  • 26
0

@RumbleFish has nicely but using ternary operation at many can make the code messy.

My approach to this is:

  • Create an Extension Function on String to replace assets/ from the path.
extension ForWeb on String {
  String forWeb({required bool web}) => web ? this.replaceFirst('assets/','') : this;
}
  • Now in code:

SvgPicture.asset("assets/images/logo.png".forWeb(web: kIsWeb));

tsvillain
  • 61
  • 1
  • 3