js-draw 0.10.2 → 0.10.3
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 +3 -0
- package/dist/bundle.js +1 -1
- package/dist/src/tools/PanZoom.d.ts +2 -1
- package/dist/src/tools/PanZoom.js +33 -17
- package/package.json +11 -11
- package/src/tools/PanZoom.ts +34 -14
@@ -25,12 +25,13 @@ export default class PanZoom extends BaseTool {
|
|
25
25
|
private lastDist;
|
26
26
|
private lastScreenCenter;
|
27
27
|
private lastTimestamp;
|
28
|
+
private lastPointerDownTimestamp;
|
28
29
|
private inertialScroller;
|
29
30
|
private velocity;
|
30
31
|
constructor(editor: Editor, mode: PanZoomMode, description: string);
|
31
32
|
computePinchData(p1: Pointer, p2: Pointer): PinchData;
|
32
33
|
private allPointersAreOfType;
|
33
|
-
onPointerDown({ allPointers: pointers }: PointerEvt): boolean;
|
34
|
+
onPointerDown({ allPointers: pointers, current: currentPointer }: PointerEvt): boolean;
|
34
35
|
private updateVelocity;
|
35
36
|
private getCenterDelta;
|
36
37
|
private handleTwoFingerMove;
|
@@ -37,19 +37,19 @@ class InertialScroller {
|
|
37
37
|
if (this.running) {
|
38
38
|
return;
|
39
39
|
}
|
40
|
-
|
40
|
+
this.currentVelocity = this.initialVelocity;
|
41
41
|
let lastTime = (new Date()).getTime();
|
42
42
|
this.running = true;
|
43
|
-
const maxSpeed =
|
43
|
+
const maxSpeed = 5000; // units/s
|
44
44
|
const minSpeed = 200; // units/s
|
45
|
-
if (currentVelocity.magnitude() > maxSpeed) {
|
46
|
-
currentVelocity = currentVelocity.normalized().times(maxSpeed);
|
45
|
+
if (this.currentVelocity.magnitude() > maxSpeed) {
|
46
|
+
this.currentVelocity = this.currentVelocity.normalized().times(maxSpeed);
|
47
47
|
}
|
48
|
-
while (this.running && currentVelocity.magnitude() > minSpeed) {
|
48
|
+
while (this.running && this.currentVelocity.magnitude() > minSpeed) {
|
49
49
|
const nowTime = (new Date()).getTime();
|
50
50
|
const dt = (nowTime - lastTime) / 1000;
|
51
|
-
currentVelocity = currentVelocity.times(Math.pow(1 / 8, dt));
|
52
|
-
this.scrollBy(currentVelocity.times(dt));
|
51
|
+
this.currentVelocity = this.currentVelocity.times(Math.pow(1 / 8, dt));
|
52
|
+
this.scrollBy(this.currentVelocity.times(dt));
|
53
53
|
yield untilNextAnimationFrame();
|
54
54
|
lastTime = nowTime;
|
55
55
|
}
|
@@ -58,6 +58,12 @@ class InertialScroller {
|
|
58
58
|
}
|
59
59
|
});
|
60
60
|
}
|
61
|
+
getCurrentVelocity() {
|
62
|
+
if (!this.running) {
|
63
|
+
return null;
|
64
|
+
}
|
65
|
+
return this.currentVelocity;
|
66
|
+
}
|
61
67
|
stop() {
|
62
68
|
if (this.running) {
|
63
69
|
this.running = false;
|
@@ -71,6 +77,7 @@ export default class PanZoom extends BaseTool {
|
|
71
77
|
this.editor = editor;
|
72
78
|
this.mode = mode;
|
73
79
|
this.transform = null;
|
80
|
+
this.lastPointerDownTimestamp = 0;
|
74
81
|
this.inertialScroller = null;
|
75
82
|
this.velocity = null;
|
76
83
|
}
|
@@ -86,10 +93,13 @@ export default class PanZoom extends BaseTool {
|
|
86
93
|
allPointersAreOfType(pointers, kind) {
|
87
94
|
return pointers.every(pointer => pointer.device === kind);
|
88
95
|
}
|
89
|
-
onPointerDown({ allPointers: pointers }) {
|
90
|
-
var _a, _b;
|
96
|
+
onPointerDown({ allPointers: pointers, current: currentPointer }) {
|
97
|
+
var _a, _b, _c, _d;
|
91
98
|
let handlingGesture = false;
|
92
|
-
(_a = this.inertialScroller) === null || _a === void 0 ? void 0 : _a.
|
99
|
+
const inertialScrollerVelocity = (_b = (_a = this.inertialScroller) === null || _a === void 0 ? void 0 : _a.getCurrentVelocity()) !== null && _b !== void 0 ? _b : Vec2.zero;
|
100
|
+
(_c = this.inertialScroller) === null || _c === void 0 ? void 0 : _c.stop();
|
101
|
+
this.velocity = inertialScrollerVelocity;
|
102
|
+
this.lastPointerDownTimestamp = currentPointer.timeStamp;
|
93
103
|
const allAreTouch = this.allPointersAreOfType(pointers, PointerDevice.Touch);
|
94
104
|
const isRightClick = this.allPointersAreOfType(pointers, PointerDevice.RightButtonMouse);
|
95
105
|
if (allAreTouch && pointers.length === 2 && this.mode & PanZoomMode.TwoFingerTouchGestures) {
|
@@ -107,22 +117,24 @@ export default class PanZoom extends BaseTool {
|
|
107
117
|
}
|
108
118
|
if (handlingGesture) {
|
109
119
|
this.lastTimestamp = (new Date()).getTime();
|
110
|
-
(
|
120
|
+
(_d = this.transform) !== null && _d !== void 0 ? _d : (this.transform = Viewport.transformBy(Mat33.identity));
|
111
121
|
this.editor.display.setDraftMode(true);
|
112
122
|
}
|
113
123
|
return handlingGesture;
|
114
124
|
}
|
115
125
|
updateVelocity(currentCenter) {
|
116
126
|
const deltaPos = currentCenter.minus(this.lastScreenCenter);
|
117
|
-
|
118
|
-
// We divide by deltaTime. Don't divide by zero.
|
119
|
-
if (deltaTime === 0) {
|
120
|
-
return;
|
121
|
-
}
|
127
|
+
let deltaTime = ((new Date()).getTime() - this.lastTimestamp) / 1000;
|
122
128
|
// Ignore duplicate events, unless there has been enough time between them.
|
123
129
|
if (deltaPos.magnitude() === 0 && deltaTime < 0.1) {
|
124
130
|
return;
|
125
131
|
}
|
132
|
+
// We divide by deltaTime. Don't divide by zero.
|
133
|
+
if (deltaTime === 0) {
|
134
|
+
return;
|
135
|
+
}
|
136
|
+
// Don't divide by almost zero, either
|
137
|
+
deltaTime = Math.max(deltaTime, 0.01);
|
126
138
|
const currentVelocity = deltaPos.times(1 / deltaTime);
|
127
139
|
let smoothedVelocity = currentVelocity;
|
128
140
|
if (this.velocity) {
|
@@ -184,7 +196,11 @@ export default class PanZoom extends BaseTool {
|
|
184
196
|
this.transform = null;
|
185
197
|
this.velocity = Vec2.zero;
|
186
198
|
};
|
187
|
-
const
|
199
|
+
const minInertialScrollDt = 30;
|
200
|
+
const shouldInertialScroll = event.current.device === PointerDevice.Touch
|
201
|
+
&& event.allPointers.length === 1
|
202
|
+
&& this.velocity !== null
|
203
|
+
&& event.current.timeStamp - this.lastPointerDownTimestamp > minInertialScrollDt;
|
188
204
|
if (shouldInertialScroll && this.velocity !== null) {
|
189
205
|
// If the user drags the screen, then stops, then lifts the pointer,
|
190
206
|
// we want the final velocity to reflect the stop at the end (so the velocity
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "js-draw",
|
3
|
-
"version": "0.10.
|
3
|
+
"version": "0.10.3",
|
4
4
|
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
|
5
5
|
"main": "./dist/src/lib.d.ts",
|
6
6
|
"types": "./dist/src/lib.js",
|
@@ -83,26 +83,26 @@
|
|
83
83
|
},
|
84
84
|
"devDependencies": {
|
85
85
|
"@types/bezier-js": "^4.1.0",
|
86
|
-
"@types/jest": "^29.2.
|
86
|
+
"@types/jest": "^29.2.5",
|
87
87
|
"@types/jsdom": "^20.0.1",
|
88
|
-
"@types/node": "^18.11.
|
88
|
+
"@types/node": "^18.11.18",
|
89
89
|
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
90
90
|
"@typescript-eslint/parser": "^5.44.0",
|
91
|
-
"css-loader": "^6.7.
|
92
|
-
"eslint": "^8.
|
93
|
-
"husky": "^8.0.
|
94
|
-
"jest": "^29.
|
91
|
+
"css-loader": "^6.7.3",
|
92
|
+
"eslint": "^8.31.0",
|
93
|
+
"husky": "^8.0.3",
|
94
|
+
"jest": "^29.3.1",
|
95
95
|
"jest-environment-jsdom": "^29.3.1",
|
96
96
|
"jsdom": "^20.0.3",
|
97
|
-
"lint-staged": "^13.0
|
97
|
+
"lint-staged": "^13.1.0",
|
98
98
|
"pinst": "^3.0.0",
|
99
99
|
"style-loader": "^3.3.1",
|
100
100
|
"terser-webpack-plugin": "^5.3.6",
|
101
101
|
"ts-jest": "^29.0.3",
|
102
|
-
"ts-loader": "^9.4.
|
102
|
+
"ts-loader": "^9.4.2",
|
103
103
|
"ts-node": "^10.9.1",
|
104
|
-
"typedoc": "^0.23.
|
105
|
-
"typescript": "^4.9.
|
104
|
+
"typedoc": "^0.23.23",
|
105
|
+
"typescript": "^4.9.4",
|
106
106
|
"webpack": "^5.75.0"
|
107
107
|
},
|
108
108
|
"bugs": {
|
package/src/tools/PanZoom.ts
CHANGED
@@ -30,6 +30,7 @@ type ScrollByCallback = (delta: Vec2) => void;
|
|
30
30
|
|
31
31
|
class InertialScroller {
|
32
32
|
private running: boolean = false;
|
33
|
+
private currentVelocity: Vec2;
|
33
34
|
|
34
35
|
public constructor(
|
35
36
|
private initialVelocity: Vec2,
|
@@ -44,22 +45,22 @@ class InertialScroller {
|
|
44
45
|
return;
|
45
46
|
}
|
46
47
|
|
47
|
-
|
48
|
+
this.currentVelocity = this.initialVelocity;
|
48
49
|
let lastTime = (new Date()).getTime();
|
49
50
|
this.running = true;
|
50
51
|
|
51
|
-
const maxSpeed =
|
52
|
+
const maxSpeed = 5000; // units/s
|
52
53
|
const minSpeed = 200; // units/s
|
53
|
-
if (currentVelocity.magnitude() > maxSpeed) {
|
54
|
-
currentVelocity = currentVelocity.normalized().times(maxSpeed);
|
54
|
+
if (this.currentVelocity.magnitude() > maxSpeed) {
|
55
|
+
this.currentVelocity = this.currentVelocity.normalized().times(maxSpeed);
|
55
56
|
}
|
56
57
|
|
57
|
-
while (this.running && currentVelocity.magnitude() > minSpeed) {
|
58
|
+
while (this.running && this.currentVelocity.magnitude() > minSpeed) {
|
58
59
|
const nowTime = (new Date()).getTime();
|
59
60
|
const dt = (nowTime - lastTime) / 1000;
|
60
61
|
|
61
|
-
currentVelocity = currentVelocity.times(Math.pow(1/8, dt));
|
62
|
-
this.scrollBy(currentVelocity.times(dt));
|
62
|
+
this.currentVelocity = this.currentVelocity.times(Math.pow(1/8, dt));
|
63
|
+
this.scrollBy(this.currentVelocity.times(dt));
|
63
64
|
|
64
65
|
await untilNextAnimationFrame();
|
65
66
|
lastTime = nowTime;
|
@@ -70,6 +71,14 @@ class InertialScroller {
|
|
70
71
|
}
|
71
72
|
}
|
72
73
|
|
74
|
+
public getCurrentVelocity(): Vec2|null {
|
75
|
+
if (!this.running) {
|
76
|
+
return null;
|
77
|
+
}
|
78
|
+
|
79
|
+
return this.currentVelocity;
|
80
|
+
}
|
81
|
+
|
73
82
|
public stop(): void {
|
74
83
|
if (this.running) {
|
75
84
|
this.running = false;
|
@@ -85,6 +94,7 @@ export default class PanZoom extends BaseTool {
|
|
85
94
|
private lastDist: number;
|
86
95
|
private lastScreenCenter: Point2;
|
87
96
|
private lastTimestamp: number;
|
97
|
+
private lastPointerDownTimestamp: number = 0;
|
88
98
|
|
89
99
|
private inertialScroller: InertialScroller|null = null;
|
90
100
|
private velocity: Vec2|null = null;
|
@@ -108,10 +118,14 @@ export default class PanZoom extends BaseTool {
|
|
108
118
|
return pointers.every(pointer => pointer.device === kind);
|
109
119
|
}
|
110
120
|
|
111
|
-
public onPointerDown({ allPointers: pointers }: PointerEvt): boolean {
|
121
|
+
public onPointerDown({ allPointers: pointers, current: currentPointer }: PointerEvt): boolean {
|
112
122
|
let handlingGesture = false;
|
113
123
|
|
124
|
+
const inertialScrollerVelocity = this.inertialScroller?.getCurrentVelocity() ?? Vec2.zero;
|
114
125
|
this.inertialScroller?.stop();
|
126
|
+
this.velocity = inertialScrollerVelocity;
|
127
|
+
|
128
|
+
this.lastPointerDownTimestamp = currentPointer.timeStamp;
|
115
129
|
|
116
130
|
const allAreTouch = this.allPointersAreOfType(pointers, PointerDevice.Touch);
|
117
131
|
const isRightClick = this.allPointersAreOfType(pointers, PointerDevice.RightButtonMouse);
|
@@ -142,17 +156,19 @@ export default class PanZoom extends BaseTool {
|
|
142
156
|
|
143
157
|
private updateVelocity(currentCenter: Point2) {
|
144
158
|
const deltaPos = currentCenter.minus(this.lastScreenCenter);
|
145
|
-
|
159
|
+
let deltaTime = ((new Date()).getTime() - this.lastTimestamp) / 1000;
|
146
160
|
|
161
|
+
// Ignore duplicate events, unless there has been enough time between them.
|
162
|
+
if (deltaPos.magnitude() === 0 && deltaTime < 0.1) {
|
163
|
+
return;
|
164
|
+
}
|
147
165
|
// We divide by deltaTime. Don't divide by zero.
|
148
166
|
if (deltaTime === 0) {
|
149
167
|
return;
|
150
168
|
}
|
151
169
|
|
152
|
-
//
|
153
|
-
|
154
|
-
return;
|
155
|
-
}
|
170
|
+
// Don't divide by almost zero, either
|
171
|
+
deltaTime = Math.max(deltaTime, 0.01);
|
156
172
|
|
157
173
|
const currentVelocity = deltaPos.times(1 / deltaTime);
|
158
174
|
let smoothedVelocity = currentVelocity;
|
@@ -233,8 +249,12 @@ export default class PanZoom extends BaseTool {
|
|
233
249
|
this.velocity = Vec2.zero;
|
234
250
|
};
|
235
251
|
|
252
|
+
const minInertialScrollDt = 30;
|
236
253
|
const shouldInertialScroll =
|
237
|
-
event.current.device === PointerDevice.Touch
|
254
|
+
event.current.device === PointerDevice.Touch
|
255
|
+
&& event.allPointers.length === 1
|
256
|
+
&& this.velocity !== null
|
257
|
+
&& event.current.timeStamp - this.lastPointerDownTimestamp > minInertialScrollDt;
|
238
258
|
|
239
259
|
if (shouldInertialScroll && this.velocity !== null) {
|
240
260
|
// If the user drags the screen, then stops, then lifts the pointer,
|