locked x axis if zoomed out
white page background dont allow drawing out of page
This commit is contained in:
parent
693d0538ef
commit
d91a834126
@ -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;
|
||||
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) {
|
||||
@ -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
|
||||
),
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
13
lib/canvas/screen_document_mapping.dart
Normal file
13
lib/canvas/screen_document_mapping.dart
Normal 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);
|
||||
}
|
@ -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';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user