js-draw 0.13.0 → 0.13.1
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.
@@ -9,7 +9,7 @@ export const makeColorInput = (editor, onColorChange) => {
|
|
9
9
|
colorInput.classList.add('coloris_input');
|
10
10
|
colorInputContainer.classList.add('color-input-container');
|
11
11
|
colorInputContainer.appendChild(colorInput);
|
12
|
-
addPipetteTool(editor, colorInputContainer, (color) => {
|
12
|
+
const pipetteController = addPipetteTool(editor, colorInputContainer, (color) => {
|
13
13
|
colorInput.value = color.toHexString();
|
14
14
|
onInputEnd();
|
15
15
|
// Update the color preview, if it exists (may be managed by Coloris).
|
@@ -41,6 +41,7 @@ export const makeColorInput = (editor, onColorChange) => {
|
|
41
41
|
kind: EditorEventType.ColorPickerToggled,
|
42
42
|
open: true,
|
43
43
|
});
|
44
|
+
pipetteController.cancel();
|
44
45
|
});
|
45
46
|
colorInput.addEventListener('close', () => {
|
46
47
|
editor.notifier.dispatch(EditorEventType.ColorPickerToggled, {
|
@@ -102,5 +103,11 @@ const addPipetteTool = (editor, container, onColorChange) => {
|
|
102
103
|
}
|
103
104
|
};
|
104
105
|
container.appendChild(pipetteButton);
|
106
|
+
return {
|
107
|
+
// Cancel a pipette color selection if one is in progress.
|
108
|
+
cancel: () => {
|
109
|
+
endColorSelectMode();
|
110
|
+
},
|
111
|
+
};
|
105
112
|
};
|
106
113
|
export default makeColorInput;
|
@@ -21,11 +21,12 @@ export default class PanZoom extends BaseTool {
|
|
21
21
|
private editor;
|
22
22
|
private mode;
|
23
23
|
private transform;
|
24
|
-
private lastAngle;
|
25
24
|
private lastDist;
|
26
25
|
private lastScreenCenter;
|
27
26
|
private lastTimestamp;
|
28
27
|
private lastPointerDownTimestamp;
|
28
|
+
private initialTouchAngle;
|
29
|
+
private initialViewportRotation;
|
29
30
|
private inertialScroller;
|
30
31
|
private velocity;
|
31
32
|
constructor(editor: Editor, mode: PanZoomMode, description: string);
|
@@ -34,6 +35,7 @@ export default class PanZoom extends BaseTool {
|
|
34
35
|
onPointerDown({ allPointers: pointers, current: currentPointer }: PointerEvt): boolean;
|
35
36
|
private updateVelocity;
|
36
37
|
private getCenterDelta;
|
38
|
+
private toSnappedRotationDelta;
|
37
39
|
private handleTwoFingerMove;
|
38
40
|
private handleOneFingerMove;
|
39
41
|
onPointerMove({ allPointers }: PointerEvt): void;
|
@@ -78,6 +78,8 @@ export default class PanZoom extends BaseTool {
|
|
78
78
|
this.mode = mode;
|
79
79
|
this.transform = null;
|
80
80
|
this.lastPointerDownTimestamp = 0;
|
81
|
+
this.initialTouchAngle = 0;
|
82
|
+
this.initialViewportRotation = 0;
|
81
83
|
this.inertialScroller = null;
|
82
84
|
this.velocity = null;
|
83
85
|
}
|
@@ -104,9 +106,10 @@ export default class PanZoom extends BaseTool {
|
|
104
106
|
const isRightClick = this.allPointersAreOfType(pointers, PointerDevice.RightButtonMouse);
|
105
107
|
if (allAreTouch && pointers.length === 2 && this.mode & PanZoomMode.TwoFingerTouchGestures) {
|
106
108
|
const { screenCenter, angle, dist } = this.computePinchData(pointers[0], pointers[1]);
|
107
|
-
this.lastAngle = angle;
|
108
109
|
this.lastDist = dist;
|
109
110
|
this.lastScreenCenter = screenCenter;
|
111
|
+
this.initialTouchAngle = angle;
|
112
|
+
this.initialViewportRotation = this.editor.viewport.getRotationAngle();
|
110
113
|
handlingGesture = true;
|
111
114
|
}
|
112
115
|
else if (pointers.length === 1 && ((this.mode & PanZoomMode.OneFingerTouchGestures && allAreTouch)
|
@@ -149,20 +152,42 @@ export default class PanZoom extends BaseTool {
|
|
149
152
|
const delta = this.editor.viewport.screenToCanvasTransform.transformVec3(screenCenter.minus(this.lastScreenCenter));
|
150
153
|
return delta;
|
151
154
|
}
|
155
|
+
// Snaps `angle` to common desired rotations. For example, if `touchAngle` corresponds
|
156
|
+
// to a viewport rotation of 90.1 degrees, this function returns a rotation delta that,
|
157
|
+
// when applied to the viewport, rotates the viewport to 90.0 degrees.
|
158
|
+
//
|
159
|
+
// Returns a snapped rotation delta that, when applied to the viewport, rotates the viewport,
|
160
|
+
// from its position on the last touchDown event, by `touchAngle - initialTouchAngle`.
|
161
|
+
toSnappedRotationDelta(touchAngle) {
|
162
|
+
const deltaAngle = touchAngle - this.initialTouchAngle;
|
163
|
+
let fullRotation = deltaAngle + this.initialViewportRotation;
|
164
|
+
const snapToMultipleOf = Math.PI / 2;
|
165
|
+
const roundedFullRotation = Math.round(fullRotation / snapToMultipleOf) * snapToMultipleOf;
|
166
|
+
// The maximum angle for which we snap the given angle to a multiple of
|
167
|
+
// `snapToMultipleOf`.
|
168
|
+
const maxSnapAngle = 0.07;
|
169
|
+
// Snap the rotation
|
170
|
+
if (Math.abs(fullRotation - roundedFullRotation) < maxSnapAngle) {
|
171
|
+
fullRotation = roundedFullRotation;
|
172
|
+
}
|
173
|
+
return fullRotation - this.editor.viewport.getRotationAngle();
|
174
|
+
}
|
152
175
|
handleTwoFingerMove(allPointers) {
|
153
176
|
const { screenCenter, canvasCenter, angle, dist } = this.computePinchData(allPointers[0], allPointers[1]);
|
154
177
|
const delta = this.getCenterDelta(screenCenter);
|
155
|
-
let
|
178
|
+
let deltaRotation;
|
156
179
|
if (this.isRotationLocked()) {
|
157
|
-
|
180
|
+
deltaRotation = 0;
|
181
|
+
}
|
182
|
+
else {
|
183
|
+
deltaRotation = this.toSnappedRotationDelta(angle);
|
158
184
|
}
|
159
185
|
this.updateVelocity(screenCenter);
|
160
186
|
const transformUpdate = Mat33.translation(delta)
|
161
187
|
.rightMul(Mat33.scaling2D(dist / this.lastDist, canvasCenter))
|
162
|
-
.rightMul(Mat33.zRotation(
|
188
|
+
.rightMul(Mat33.zRotation(deltaRotation, canvasCenter));
|
163
189
|
this.lastScreenCenter = screenCenter;
|
164
190
|
this.lastDist = dist;
|
165
|
-
this.lastAngle = angle;
|
166
191
|
this.transform = Viewport.transformBy(this.transform.transform.rightMul(transformUpdate));
|
167
192
|
}
|
168
193
|
handleOneFingerMove(pointer) {
|
package/package.json
CHANGED
@@ -19,7 +19,7 @@ export const makeColorInput = (
|
|
19
19
|
colorInputContainer.classList.add('color-input-container');
|
20
20
|
|
21
21
|
colorInputContainer.appendChild(colorInput);
|
22
|
-
addPipetteTool(editor, colorInputContainer, (color: Color4) => {
|
22
|
+
const pipetteController = addPipetteTool(editor, colorInputContainer, (color: Color4) => {
|
23
23
|
colorInput.value = color.toHexString();
|
24
24
|
onInputEnd();
|
25
25
|
|
@@ -58,6 +58,7 @@ export const makeColorInput = (
|
|
58
58
|
kind: EditorEventType.ColorPickerToggled,
|
59
59
|
open: true,
|
60
60
|
});
|
61
|
+
pipetteController.cancel();
|
61
62
|
});
|
62
63
|
colorInput.addEventListener('close', () => {
|
63
64
|
editor.notifier.dispatch(EditorEventType.ColorPickerToggled, {
|
@@ -132,6 +133,13 @@ const addPipetteTool = (editor: Editor, container: HTMLElement, onColorChange: O
|
|
132
133
|
};
|
133
134
|
|
134
135
|
container.appendChild(pipetteButton);
|
136
|
+
|
137
|
+
return {
|
138
|
+
// Cancel a pipette color selection if one is in progress.
|
139
|
+
cancel: () => {
|
140
|
+
endColorSelectMode();
|
141
|
+
},
|
142
|
+
};
|
135
143
|
};
|
136
144
|
|
137
145
|
export default makeColorInput;
|
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
|
);
|