Search code examples
flutterdartpdfsyncfusion

How to add Circular shape in existing pdf file using syncfusion flutter pdf package?


In flutter i want to add circular shape in existing pdf file using this code

document.pages[0].graphics.drawPie(Rect.fromLTWH(dx, dy, 50, 50), 0, 360,brush: PdfBrushes.green);

And this is how i am showing my pdf file using this code

SfPdfViewer.memory( documentBytes!, key: _pdfViewerKey, controller: _pdfViewerController, onDocumentLoaded: (PdfDocumentLoadedDetails details) { _pdfViewerController.jumpTo( xOffset: xOffset, yOffset: yOffset); }, )

now i want this circular shape at where i tap on the pdf file exact location .. right now if you want to check run below full code and move the circle with your finger tap on that circle and press appbar save button it show you green dot circle shape but it not at exact location.

Full Running Code

     import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:syncfusion_flutter_pdf/pdf.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';

import 'global.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

/// Represents Homepage for Navigation
class HomePage extends StatefulWidget {
  @override
  _HomePage createState() => _HomePage();
}

class _HomePage extends State<HomePage> {
  final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
  final PdfViewerController _pdfViewerController = PdfViewerController();
  OverlayEntry? _overlayEntry;
  double yOffset = 0.0;
  double xOffset = 0.0;
  final Color _contextMenuColor = const Color(0xFFFFFFFF);
  final Color _textColor = const Color(0xFF000000);

  @override
  void initState() {
    getPdfBytes();

    super.initState();
  }

  PdfPolygonAnnotation? polygonAnnotation;
  double x = 0.0;
  double y = 0.0;
  double fontSize = 26.0;
  double scalingFactor = 1.5; // Adjust this value to control the speed
  Offset startPoint = Offset.zero;
  TextEditingController editableText = TextEditingController();
  File? file;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Syncfusion Flutter PDF Viewer'),
        actions: [
          GestureDetector(
              onTapUp: (TapUpDetails details) {
                print(
                    'DXDYDXDY 11 : ${details.globalPosition.dx}, dy: ${details.globalPosition.dy}');
              },
              onTap: () async {
                final PdfDocument document =
                    PdfDocument(inputBytes: documentBytes);
                // document.pages[0].graphics.drawPie(
                //     Rect.fromLTWH(400, 700, 50, 50), 0, 360,
                //     brush: PdfBrushes.green);

                document.pages[0].graphics.drawPie(
                    Rect.fromLTWH(dx, dy, 50, 50), 0, 360,
                    brush: PdfBrushes.green);
                print('dxdxdx :: ${dx}');
                print('dydydy :: ${dy}'); // _pdfViewerKey.currentContext.re
                final List<int> bytes = document.saveSync();
                setState(() {
                  documentBytes = Uint8List.fromList(bytes);
                });
                document.dispose();
              },
              child: Icon(Icons.save)),
          SizedBox(
            width: 40,
          )
        ],
      ),
      body: documentBytes != null
          ? Stack(
              children: [
                SfPdfViewer.memory(
                  documentBytes!,
                  key: _pdfViewerKey,
                  controller: _pdfViewerController,
                  onDocumentLoaded: (PdfDocumentLoadedDetails details) {
                    _pdfViewerController.jumpTo(
                        xOffset: xOffset, yOffset: yOffset);
                  },
                ),
                AnnotationPage(),
              ],
            )
          : Container(),
    );
  }

  ///Get the PDF document as bytes
  void getPdfBytes() async {
    documentBytes =
        await http.readBytes(Uri.parse('https://pdfobject.com/pdf/sample.pdf'));
    setState(() {});
  }
}

class AnnotationPage extends StatefulWidget {
  const AnnotationPage({Key? key}) : super(key: key);

  @override
  _AnnotationPageState createState() => _AnnotationPageState();
}

class _AnnotationPageState extends State<AnnotationPage> {
  double x = 0.0;
  double y = 0.0;
  double fontSize = 26.0;
  double scalingFactor = 1.5; // Adjust this value to control the speed
  Offset startPoint = Offset.zero;
  TextEditingController editableText = TextEditingController();
  File? file;

  @override
  void initState() {
    super.initState();
    editableText.text = 'Add Text Here';
  }

  @override
  Widget build(BuildContext context) {
    return Positioned(
      left: x,
      top: y,
      child: Stack(
        children: [
          GestureDetector(
            onScaleStart: (details) {
              startPoint = details.focalPoint;
            },
            onTapUp: (TapUpDetails details) {
              print(
                  'DXDYDXDY  22: ${details.globalPosition.dx}, dy: ${details.globalPosition.dy}');
              dx = details.globalPosition.dx;
              dy = details.globalPosition.dy;
            },
            onScaleUpdate: (details) {
              setState(() {
                x += (details.focalPoint.dx - startPoint.dx) * scalingFactor;
                y += (details.focalPoint.dy - startPoint.dy) * scalingFactor;
                fontSize = (fontSize * details.scale).clamp(16.0, 120.0);
                startPoint = details.focalPoint;
                // dx = details.focalPoint.dx;
                // dy = details.focalPoint.dy;
                // dx = x;
                // dy = y;
                print('DXDX :: ${x}');
                print('DYDY :: ${y}');
              });
            },
            child: Container(
                child: Icon(
              Icons.circle_outlined,
              size: 50,
            )

                // Text(
                //   editableText.text,
                //   style: TextStyle(fontSize: fontSize),
                // ),
                ),
          ),
        ],
      ),
    );
  }
}

In simple i want to add that shape at exact location of my tap on pdf.


Solution

  • To get the tapped page number and tapped page position, you can use the onTap callback of the Flutter PDF viewer widget.

    class PdfViewerPage extends StatefulWidget {
      const PdfViewerPage({super.key});
    
      @override
      State<PdfViewerPage> createState() => _PdfViewerPageState();
    }
    
    class _PdfViewerPageState extends State<PdfViewerPage> {
      final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
      final PdfViewerController _pdfViewerController = PdfViewerController();
    
      PdfDocument? _loadedDocument;
    
      Uint8List? _documentBytes;
      int _tappedPageNumber = 0;
      Offset _tappedOffset = Offset.zero;
    
      Offset? _offset;
      double? _zoomLevel;
    
      double _circleSize = 50;
    
      @override
      void initState() {
        _getPdfBytes();
    
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Syncfusion Flutter PDF Viewer'),
          ),
          body: _documentBytes != null
              ? SfPdfViewer.memory(
                  _documentBytes!,
                  key: _pdfViewerKey,
                  controller: _pdfViewerController,
                  initialZoomLevel: _zoomLevel ?? 1.0,
                  onDocumentLoaded: (PdfDocumentLoadedDetails details) {
                    _loadedDocument = details.document;
    
                    if (_offset != null) {
                      _pdfViewerController.jumpTo(
                          xOffset: _offset!.dx, yOffset: _offset!.dy);
                    }
                  },
                  onTap: (PdfGestureDetails details) {
                    _offset = _pdfViewerController.scrollOffset;
                    _tappedPageNumber = details.pageNumber;
                    _tappedOffset = details.pagePosition;
                    _zoomLevel = _pdfViewerController.zoomLevel;
    
                    _addCircle();
                  },
                )
              : null,
        );
      }
    
      void _addCircle() async {
        if (_loadedDocument != null) {
          final PdfPage page = _loadedDocument!.pages[_tappedPageNumber - 1];
    
          page.graphics.drawEllipse(
            Rect.fromLTWH(_tappedOffset.dx - _circleSize / 2,
                _tappedOffset.dy - _circleSize / 2, _circleSize, _circleSize),
            brush: PdfBrushes.green,
          );
    
          final List<int> bytes = await _loadedDocument!.save();
          setState(() {
            _documentBytes = Uint8List.fromList(bytes);
          });
        }
      }
    
      ///Get the PDF document as bytes
      void _getPdfBytes() async {
        _documentBytes =
            await http.readBytes(Uri.parse('https://pdfobject.com/pdf/sample.pdf'));
        setState(() {});
      }
    }