5

I am creating a note-taking app using Flutter and I use a CustomPainter for the drawing part. For better performance, the CustomPaint gets converted into an image after some Lines. Now the problem with images is when zooming in, the lines (which are Images now) are very pixelated. Now my first Idea to solve this was redrawing the lines after zooming.

But how do I redraw them correctly without them still having a bad resolution? Also, is it possible to only redraw the lines that are visible on the screen currently?

everything is wrapped with a layoutbuilder which provides constraints + pixelratio (scale):

    LayoutBuilder(builder: (context, constraints) {
          size = constraints.biggest;
          scale = MediaQuery.of(context).devicePixelRatio;

How I did the zooming:

                  GestureDetector(
                    onScaleStart: (details) {
                      _initialFocalPoint = details.focalPoint;
                      _initialScale = _scale;
                    },
                    onScaleUpdate: (details) {
                      setState(() {
                        _sessionOffset =
                            details.focalPoint - _initialFocalPoint;

                        _scale = _initialScale * details.scale;
                      });
                    },
                    onScaleEnd: (details) {
                      setState(() {
                        _offset += _sessionOffset;
                        _sessionOffset = Offset.zero;
                      });
                    },
                    child: Transform.translate(
                        offset: _offset + _sessionOffset,
                        child: Transform.scale(
                          scale: _scale,
                          child: .... 

my CustomPaint which comes somewhere after the Transform widgets:

                               CustomPaint(
                                  size: size!,
                                  willChange: true,
                                  painter: DrawingViewPainter(
                                      pointsList: drawingNotifier.points,
                                      image: image
                                  ),
                                );

snippet with the custpmpaint to image converter (drawn lines get converted to images to save performance):

  ui.PictureRecorder recorder = ui.PictureRecorder();
  Canvas canvas = ui.Canvas(recorder);
  canvas.scale(scale!);

  DrawingViewPainter(image: image, pointsList: points).paint(canvas, size!);
  ui.Picture picture = recorder.endRecording();
  ui.Image newImage = await picture.toImage(
    (size!.width * scale!).ceil(),
    (size!.height * scale!).ceil(),
  );
......
image = newImage

the Custompaint part with the image drawer:

canvas.drawImageRect(
          image!,
          Offset.zero & Size(image!.width.toDouble(), image!.height.toDouble()),
          Offset.zero & size,
          Paint());
    }

(sorry for the huge amount of code)

If you know of a better way please let me know as well.

Here a video of the Problem

Yusuf-Uluc
  • 887
  • 4
  • 15
  • In paint class there is a flag called anti-aliasing set it to true you will have smoother edges. – MRamzan Sep 25 '21 at 08:21
  • @MRamzan this changes nearly nothing – Yusuf-Uluc Sep 25 '21 at 08:49
  • please refer to this answer that might help understand the concept or read the whole thread. https://stackoverflow.com/a/64090316/9411376 – MRamzan Sep 25 '21 at 09:02
  • this is not exactly what I need @MRamzan – Yusuf-Uluc Sep 25 '21 at 09:13
  • Are you sure you get better performance? In my use case I simply draw all curves and it is quite fast even when rerendering every frame. – ch271828n Sep 26 '21 at 01:10
  • 2
    That doesn't really answer your question, but please have a look at `InteractiveViewer` (https://api.flutter.dev/flutter/widgets/InteractiveViewer-class.html) which provides zooming and dragging functionality out of the box. You might not need to implement that yourself – tmaihoff Sep 30 '21 at 08:30

0 Answers0