diff --git a/lib/canvas/drawing_page.dart b/lib/canvas/drawing_page.dart index 638754b..0a1401e 100644 --- a/lib/canvas/drawing_page.dart +++ b/lib/canvas/drawing_page.dart @@ -1,9 +1,7 @@ -import 'dart:math'; import 'dart:ui'; - -import 'package:equations/equations.dart'; import 'package:flutter/material.dart'; import 'package:notes/canvas/my_painter.dart'; +import 'package:notes/canvas/screen_document_mapping.dart'; import 'document_types.dart'; @@ -18,8 +16,9 @@ class _DrawingPageState extends State { List _strokes = []; bool allowDrawWithFinger = false; - double zoom = .5; - Offset scrollPos = const Offset(.0, .0); + double zoom = .75; + double basezoom = 1.0; + Offset offset = const Offset(.0, .0); @override Widget build(BuildContext context) { @@ -37,57 +36,102 @@ class _DrawingPageState extends State { return basetickness; // todo do correct linear interpolation and extimate angle - final lininterpol = PolynomialInterpolation( - nodes: pts - .map((e) => InterpolationNode(x: e.point.dx, y: e.point.dy)) - .toList(growable: false)); - lininterpol.compute(1.0); - print(lininterpol.buildPolynomial().toString()); - - // double angle = atan((pt2.dy - pt1.dy)/(pt2.dx - pt1.dx)); - - final angle = 5 / (2 * pi); - // print("pt1: ${pt1}, pt2: ${pt2}, angle: ${angle}"); - - return basetickness * (angle / .5 + .5); + // final lininterpol = PolynomialInterpolation( + // nodes: pts + // .map((e) => InterpolationNode(x: e.point.dx, y: e.point.dy)) + // .toList(growable: false)); + // lininterpol.compute(1.0); + // print(lininterpol.buildPolynomial().toString()); + // + // // double angle = atan((pt2.dy - pt1.dy)/(pt2.dx - pt1.dx)); + // + // final angle = 5 / (2 * pi); + // // print("pt1: ${pt1}, pt2: ${pt2}, angle: ${angle}"); + // + // return basetickness * (angle / .5 + .5); } Widget _buildCanvas() { final width = MediaQuery.of(context).size.width; - - final zoomedwidth = width * zoom; + final height = MediaQuery.of(context).size.height; return Scaffold( body: Listener( + behavior: HitTestBehavior.opaque, onPointerMove: (event) { - // print(event.tilt); - final pos = event.localPosition; - final pts = _strokes.last.points; + Offset pos = event.localPosition; + final scale = + calcPageDependentScale(zoom, a4Page, Size(width, height)); + pos = translateScreenToDocumentPoint(pos, scale, offset); - if(pts.last.point == pos) return; + if (!a4Page.contains(pos)) { + return; + } if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) { + final pts = _strokes.last.points; + + if (pts.last.point == pos) return; + double newWidth = _calcTiltedWidth(3.0, event.tilt); - if(_strokes.last.points.length > 1){ + if (_strokes.last.points.length > 1) { // todo current point not in list - newWidth = _calcAngleDependentWidth(pts.getRange(pts.length - 10 >= 0 ? pts.length -10 : 0, pts.length).toList(growable: false), event.tilt); + newWidth = _calcAngleDependentWidth( + pts + .getRange(pts.length - 10 >= 0 ? pts.length - 10 : 0, + pts.length) + .toList(growable: false), + event.tilt); } setState(() { _strokes = List.from(_strokes, growable: false) ..last.points.add(Point(pos, newWidth)); }); + } else { + if (zoom > 1.0) { + Offset newOffset = offset + event.delta; + // don't allow navigating out of page if zoomed in + if (newOffset.dx > .0) { + setState(() { + offset = Offset(.0, newOffset.dy); + }); + } else if (newOffset.dx < (-width * zoom) + width) { + setState(() { + offset = Offset((-width * zoom) + width, newOffset.dy); + }); + print(offset); + } else { + setState(() { + offset = offset + event.delta; + }); + } + } else { + setState(() { + // keep page x centered if zoomed out + offset = Offset( + (width - (width * zoom)) / 2, offset.dy + event.delta.dy); + }); + } } }, onPointerDown: (event) { if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) { + Offset pos = event.localPosition; + final scale = + calcPageDependentScale(zoom, a4Page, Size(width, height)); + pos = translateScreenToDocumentPoint(pos, scale, offset); + + // todo line drawn on edge where line left page + if (!a4Page.contains(pos)) return; + setState(() { _strokes = List.from(_strokes) - ..add(Stroke.fromPoints([Point(event.localPosition, _calcTiltedWidth(3.0, event.tilt))])); + ..add(Stroke.fromPoints( + [Point(pos, _calcTiltedWidth(3.0, event.tilt))])); }); } }, - onPointerUp: (event) { if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) { if (_strokes.last.points.length <= 1) { @@ -106,15 +150,21 @@ class _DrawingPageState extends State { } }, child: GestureDetector( - onScaleUpdate: (details) { - setState(() { - zoom = details.scale; - }); - }, - child: CustomPaint( - painter: MyPainter(strokes: _strokes,offset: scrollPos, zoom: zoom), - // todo not working - size: Size.infinite, // todo add different paper dimensions + onScaleUpdate: (details) { + if (details.scale == 1.0) return; + + print('scale; ${details.scale}'); + setState(() { + zoom = (basezoom * details.scale).clamp(0.25, 5.0); + }); + }, + onScaleEnd: (details) { + basezoom = zoom; + }, + child: CustomPaint( + painter: MyPainter(strokes: _strokes, offset: offset, zoom: zoom), + // todo not working + size: Size.infinite, // todo add different paper dimensions ), ), ), diff --git a/lib/canvas/my_painter.dart b/lib/canvas/my_painter.dart index c2d2abf..bae0b73 100644 --- a/lib/canvas/my_painter.dart +++ b/lib/canvas/my_painter.dart @@ -1,7 +1,13 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; +import 'package:notes/canvas/screen_document_mapping.dart'; import 'document_types.dart'; +final Rect a4Page = + Rect.fromPoints(const Offset(.0, .0), const Offset(210, 210 * sqrt2)); + class MyPainter extends CustomPainter { List strokes; double zoom; @@ -9,40 +15,43 @@ class MyPainter extends CustomPainter { MyPainter({required this.strokes, required this.zoom, required this.offset}); + Offset _translatept(Offset pt, Size canvasSize) { + final scale = calcPageDependentScale(zoom, a4Page, canvasSize); + return translateDocumentToScreenPoint(pt, scale, offset); + } + + Paint backgroundPaint = Paint()..color = Colors.white; + @override void paint(Canvas canvas, Size size) { var paint = Paint() ..color = Colors.blue ..strokeCap = StrokeCap.square; + canvas.drawColor(const Color(0xff3f3f3f), BlendMode.src); + canvas.drawRect( + Rect.fromPoints(_translatept(const Offset(0, .0), size), + _translatept(a4Page.bottomRight, size)), + backgroundPaint); - - // ..strokeWidth = 3.0; - // canvas.scale(zoom); - print("zoom: ${zoom}"); - canvas.drawColor(Color.fromRGBO(255, 255, 255, .1), BlendMode.src); - - final pagewidth = size.width * zoom; - - final sidewidth = (size.width - pagewidth) / 2; - canvas.drawLine(Offset(sidewidth, .0), Offset(sidewidth, size.height), paint); - canvas.drawLine(Offset(sidewidth + pagewidth, .0), Offset(sidewidth + pagewidth, size.height), paint); - - for(final stroke in strokes){ - for(int i = 0; i < stroke.points.length -1; i++){ - final pt1 = stroke.points[i].point; - final pt2 = stroke.points[i+1].point; + for (final stroke in strokes) { + for (int i = 0; i < stroke.points.length - 1; i++) { + Offset pt1 = stroke.points[i].point; + pt1 = _translatept(pt1, size); + Offset pt2 = stroke.points[i + 1].point; + pt2 = _translatept(pt2, size); // final strokewidth = _calcAngleDependentWidth(pt1, pt2, stroke.points[i].thickness); - canvas.drawLine(pt1, pt2, paint..strokeWidth = stroke.points[i].thickness); + canvas.drawLine( + pt1, pt2, paint..strokeWidth = stroke.points[i].thickness); } } - - } @override bool shouldRepaint(MyPainter oldDelegate) { - return oldDelegate.strokes != strokes; + return oldDelegate.strokes != strokes || + oldDelegate.zoom != zoom || + oldDelegate.offset != offset; } } diff --git a/lib/canvas/screen_document_mapping.dart b/lib/canvas/screen_document_mapping.dart new file mode 100644 index 0000000..1a138ee --- /dev/null +++ b/lib/canvas/screen_document_mapping.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +Offset translateScreenToDocumentPoint(Offset pt, double scale, Offset offset) { + return pt.translate(-offset.dx, -offset.dy).scale(1 / scale, 1 / scale); +} + +Offset translateDocumentToScreenPoint(Offset pt, double scale, Offset offset) { + return pt.scale(scale, scale).translate(offset.dx, offset.dy); +} + +double calcPageDependentScale(double scale, Rect page, Size canvasSize) { + return scale * (canvasSize.width / page.width); +} diff --git a/lib/CollapseDrawer.dart b/lib/collapse_drawer.dart similarity index 100% rename from lib/CollapseDrawer.dart rename to lib/collapse_drawer.dart diff --git a/lib/main.dart b/lib/main.dart index 5f232f8..4d470ce 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:notes/CollapseDrawer.dart'; +import 'package:notes/collapse_drawer.dart'; import 'package:notes/all_notes_page.dart'; import 'package:notes/canvas/drawing_page.dart';