svgflutterdartpaint

Flutter draw SVG in CustomPaint (Canvas)


I have something like this:

CustomPaint(
       painter: CurvePainter(),
)

In this class I am doing my painting:

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import './myState.dart';
import './models/mode.dart';
final String rawSvg = '''<svg viewBox="...">...</svg>''';

class CurvePainter extends CustomPainter {
  MyState _myState;
  DrawableRoot svgRoot;
  CurvePainter(MyState myState) {
    this._myState = myState;
    this.loadAsset();
  }

  void loadAsset() async {
    this.svgRoot = await svg.fromSvgString(rawSvg, rawSvg);// The canvas that is your board.
  }

  @override
  void paint (Canvas canvas, Size size) {
    canvas.translate(_myState.translateX, _myState.translateY);
    if(this.svgRoot != null){
        svgRoot.scaleCanvasToViewBox(canvas, size);
        svgRoot.clipCanvasToViewBox(canvas);
        // svgRoot.draw(canvas, size);
    }
}

Somebody know how to draw a SVG inside paint method? I found this library https://pub.dev/packages/flutter_svg#-readme-tab- . With my code I get error: Unhandled Exception: Bad state: viewBox element must be 4 elements long

I would be nice, if I can scale and rotate the svg inside canvas. But this is optional.


Solution

  • From the README:

    import 'package:flutter_svg/flutter_svg.dart';
    final String rawSvg = '''<svg viewBox="...">...</svg>''';
    final DrawableRoot svgRoot = await svg.fromSvgString(rawSvg, rawSvg);
    
    // 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);
    

    Which you could adapt as:

    class CurvePainter extends CustomPainter {
      CurvePainter(this.svg);
    
      final DrawableRoot svg;
      @override
      void paint(Canvas canvas, Size size) {
           canvas.drawLine(...);
           svg.scaleCanvasToViewBox(canvas);
           svg.clipCanvasToViewBox(canvas);
           svg.draw(canvas, size);
      }
    }
    

    I'd advise finding some way to get the asynchronous part earlier on in your app, perhaps using a FutureBuilder or a ValueListenableBuilder.

    Disclosure: I'm the author/primary maintainer of Flutter SVG.