js-draw 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/dist/bundle.js +1 -1
- package/dist/src/Editor.js +4 -4
- package/dist/src/SVGLoader.js +8 -2
- package/dist/src/Viewport.d.ts +1 -0
- package/dist/src/Viewport.js +6 -3
- package/dist/src/math/Path.js +10 -3
- package/dist/src/toolbar/IconProvider.d.ts +28 -2
- package/dist/src/toolbar/IconProvider.js +27 -2
- package/dist/src/toolbar/makeColorInput.js +8 -1
- package/dist/src/tools/PanZoom.d.ts +3 -1
- package/dist/src/tools/PanZoom.js +30 -5
- package/dist/src/tools/SelectionTool/Selection.d.ts +6 -0
- package/dist/src/tools/SelectionTool/Selection.js +12 -3
- package/dist/src/tools/SelectionTool/SelectionTool.js +5 -3
- package/dist/src/tools/SelectionTool/TransformMode.js +1 -1
- package/package.json +1 -1
- package/src/Editor.ts +4 -4
- package/src/SVGLoader.ts +9 -2
- package/src/Viewport.ts +7 -3
- package/src/math/Path.toString.test.ts +10 -0
- package/src/math/Path.ts +11 -3
- package/src/toolbar/IconProvider.ts +28 -6
- package/src/toolbar/makeColorInput.ts +9 -1
- package/src/toolbar/toolbar.css +3 -0
- package/src/tools/PanZoom.ts +36 -6
- package/src/tools/SelectionTool/Selection.ts +16 -5
- package/src/tools/SelectionTool/SelectionTool.ts +5 -4
- package/src/tools/SelectionTool/TransformMode.ts +1 -1
package/src/tools/PanZoom.ts
CHANGED
@@ -90,11 +90,12 @@ class InertialScroller {
|
|
90
90
|
export default class PanZoom extends BaseTool {
|
91
91
|
private transform: ViewportTransform|null = null;
|
92
92
|
|
93
|
-
private lastAngle: number;
|
94
93
|
private lastDist: number;
|
95
94
|
private lastScreenCenter: Point2;
|
96
95
|
private lastTimestamp: number;
|
97
96
|
private lastPointerDownTimestamp: number = 0;
|
97
|
+
private initialTouchAngle: number = 0;
|
98
|
+
private initialViewportRotation: number = 0;
|
98
99
|
|
99
100
|
private inertialScroller: InertialScroller|null = null;
|
100
101
|
private velocity: Vec2|null = null;
|
@@ -132,9 +133,11 @@ export default class PanZoom extends BaseTool {
|
|
132
133
|
|
133
134
|
if (allAreTouch && pointers.length === 2 && this.mode & PanZoomMode.TwoFingerTouchGestures) {
|
134
135
|
const { screenCenter, angle, dist } = this.computePinchData(pointers[0], pointers[1]);
|
135
|
-
this.lastAngle = angle;
|
136
136
|
this.lastDist = dist;
|
137
137
|
this.lastScreenCenter = screenCenter;
|
138
|
+
this.initialTouchAngle = angle;
|
139
|
+
this.initialViewportRotation = this.editor.viewport.getRotationAngle();
|
140
|
+
|
138
141
|
handlingGesture = true;
|
139
142
|
} else if (pointers.length === 1 && (
|
140
143
|
(this.mode & PanZoomMode.OneFingerTouchGestures && allAreTouch)
|
@@ -188,24 +191,51 @@ export default class PanZoom extends BaseTool {
|
|
188
191
|
return delta;
|
189
192
|
}
|
190
193
|
|
194
|
+
// Snaps `angle` to common desired rotations. For example, if `touchAngle` corresponds
|
195
|
+
// to a viewport rotation of 90.1 degrees, this function returns a rotation delta that,
|
196
|
+
// when applied to the viewport, rotates the viewport to 90.0 degrees.
|
197
|
+
//
|
198
|
+
// Returns a snapped rotation delta that, when applied to the viewport, rotates the viewport,
|
199
|
+
// from its position on the last touchDown event, by `touchAngle - initialTouchAngle`.
|
200
|
+
private toSnappedRotationDelta(touchAngle: number) {
|
201
|
+
const deltaAngle = touchAngle - this.initialTouchAngle;
|
202
|
+
let fullRotation = deltaAngle + this.initialViewportRotation;
|
203
|
+
|
204
|
+
const snapToMultipleOf = Math.PI / 2;
|
205
|
+
const roundedFullRotation = Math.round(fullRotation / snapToMultipleOf) * snapToMultipleOf;
|
206
|
+
|
207
|
+
// The maximum angle for which we snap the given angle to a multiple of
|
208
|
+
// `snapToMultipleOf`.
|
209
|
+
const maxSnapAngle = 0.07;
|
210
|
+
|
211
|
+
// Snap the rotation
|
212
|
+
if (Math.abs(fullRotation - roundedFullRotation) < maxSnapAngle) {
|
213
|
+
fullRotation = roundedFullRotation;
|
214
|
+
}
|
215
|
+
|
216
|
+
return fullRotation - this.editor.viewport.getRotationAngle();
|
217
|
+
}
|
218
|
+
|
191
219
|
private handleTwoFingerMove(allPointers: Pointer[]) {
|
192
220
|
const { screenCenter, canvasCenter, angle, dist } = this.computePinchData(allPointers[0], allPointers[1]);
|
193
221
|
|
194
222
|
const delta = this.getCenterDelta(screenCenter);
|
195
|
-
let
|
223
|
+
let deltaRotation;
|
196
224
|
|
197
225
|
if (this.isRotationLocked()) {
|
198
|
-
|
226
|
+
deltaRotation = 0;
|
227
|
+
} else {
|
228
|
+
deltaRotation = this.toSnappedRotationDelta(angle);
|
199
229
|
}
|
200
230
|
|
231
|
+
|
201
232
|
this.updateVelocity(screenCenter);
|
202
233
|
|
203
234
|
const transformUpdate = Mat33.translation(delta)
|
204
235
|
.rightMul(Mat33.scaling2D(dist / this.lastDist, canvasCenter))
|
205
|
-
.rightMul(Mat33.zRotation(
|
236
|
+
.rightMul(Mat33.zRotation(deltaRotation, canvasCenter));
|
206
237
|
this.lastScreenCenter = screenCenter;
|
207
238
|
this.lastDist = dist;
|
208
|
-
this.lastAngle = angle;
|
209
239
|
this.transform = Viewport.transformBy(
|
210
240
|
this.transform!.transform.rightMul(transformUpdate)
|
211
241
|
);
|
@@ -121,6 +121,21 @@ export default class Selection {
|
|
121
121
|
return this.originalRegion.transformedBoundingBox(scaleAndTranslateMat);
|
122
122
|
}
|
123
123
|
|
124
|
+
/**
|
125
|
+
* Computes and returns the bounding box of the selection without
|
126
|
+
* any additional padding. Computes directly from the elements that are selected.
|
127
|
+
* @internal
|
128
|
+
*/
|
129
|
+
public computeTightBoundingBox() {
|
130
|
+
const bbox = this.selectedElems.reduce((
|
131
|
+
accumulator: Rect2|null, elem: AbstractComponent
|
132
|
+
): Rect2 => {
|
133
|
+
return (accumulator ?? elem.getBBox()).union(elem.getBBox());
|
134
|
+
}, null);
|
135
|
+
|
136
|
+
return bbox ?? Rect2.empty;
|
137
|
+
}
|
138
|
+
|
124
139
|
public get regionRotation(): number {
|
125
140
|
return this.transform.transformVec3(Vec2.unitX).angle();
|
126
141
|
}
|
@@ -328,11 +343,7 @@ export default class Selection {
|
|
328
343
|
// Recompute this' region from the selected elements.
|
329
344
|
// Returns false if the selection is empty.
|
330
345
|
public recomputeRegion(): boolean {
|
331
|
-
const newRegion = this.
|
332
|
-
accumulator: Rect2|null, elem: AbstractComponent
|
333
|
-
): Rect2 => {
|
334
|
-
return (accumulator ?? elem.getBBox()).union(elem.getBBox());
|
335
|
-
}, null);
|
346
|
+
const newRegion = this.computeTightBoundingBox();
|
336
347
|
|
337
348
|
if (!newRegion) {
|
338
349
|
this.cancelSelection();
|
@@ -62,12 +62,13 @@ export default class SelectionTool extends BaseTool {
|
|
62
62
|
private snapSelectionToGrid() {
|
63
63
|
if (!this.selectionBox) throw new Error('No selection to snap!');
|
64
64
|
|
65
|
-
|
66
|
-
const
|
67
|
-
|
65
|
+
// Snap the top left corner of what we have selected.
|
66
|
+
const topLeftOfBBox = this.selectionBox.computeTightBoundingBox().topLeft;
|
67
|
+
const snappedTopLeft = this.editor.viewport.snapToGrid(topLeftOfBBox);
|
68
|
+
const snapDelta = snappedTopLeft.minus(topLeftOfBBox);
|
68
69
|
|
69
70
|
const oldTransform = this.selectionBox.getTransform();
|
70
|
-
this.selectionBox.setTransform(oldTransform.rightMul(Mat33.translation(
|
71
|
+
this.selectionBox.setTransform(oldTransform.rightMul(Mat33.translation(snapDelta)));
|
71
72
|
this.selectionBox.finalizeTransform();
|
72
73
|
}
|
73
74
|
|
@@ -62,7 +62,7 @@ export class ResizeTransformer {
|
|
62
62
|
// long decimal representations => large file sizes.
|
63
63
|
scale = scale.map(component => Viewport.roundScaleRatio(component, 2));
|
64
64
|
|
65
|
-
if (scale.x
|
65
|
+
if (scale.x !== 0 && scale.y !== 0) {
|
66
66
|
const origin = this.editor.viewport.roundPoint(this.selection.preTransformRegion.topLeft);
|
67
67
|
this.selection.setTransform(Mat33.scaling2D(scale, origin));
|
68
68
|
}
|