locked x axis if zoomed out

white page background
dont allow drawing out of page
This commit is contained in:
lukas-heiligenbrunner 2022-10-27 00:15:13 +02:00
parent 693d0538ef
commit d91a834126
5 changed files with 130 additions and 58 deletions

View File

@ -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<DrawingPage> {
List<Stroke> _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<DrawingPage> {
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;
Offset pos = event.localPosition;
final scale =
calcPageDependentScale(zoom, a4Page, Size(width, height));
pos = translateScreenToDocumentPoint(pos, scale, offset);
if (!a4Page.contains(pos)) {
return;
}
if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) {
final pts = _strokes.last.points;
if (pts.last.point == pos) return;
if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) {
double newWidth = _calcTiltedWidth(3.0, event.tilt);
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) {
@ -107,12 +151,18 @@ class _DrawingPageState extends State<DrawingPage> {
},
child: GestureDetector(
onScaleUpdate: (details) {
if (details.scale == 1.0) return;
print('scale; ${details.scale}');
setState(() {
zoom = details.scale;
zoom = (basezoom * details.scale).clamp(0.25, 5.0);
});
},
onScaleEnd: (details) {
basezoom = zoom;
},
child: CustomPaint(
painter: MyPainter(strokes: _strokes,offset: scrollPos, zoom: zoom),
painter: MyPainter(strokes: _strokes, offset: offset, zoom: zoom),
// todo not working
size: Size.infinite, // todo add different paper dimensions
),

View File

@ -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<Stroke> 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;
// ..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);
canvas.drawColor(const Color(0xff3f3f3f), BlendMode.src);
canvas.drawRect(
Rect.fromPoints(_translatept(const Offset(0, .0), size),
_translatept(a4Page.bottomRight, size)),
backgroundPaint);
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;
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;
}
}

View File

@ -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);
}

View File

@ -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';