js-draw 1.7.2 → 1.8.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.
Files changed (47) hide show
  1. package/dist/Editor.css +1 -0
  2. package/dist/bundle.js +2 -2
  3. package/dist/bundledStyles.js +1 -1
  4. package/dist/cjs/EventDispatcher.js +2 -1
  5. package/dist/cjs/Viewport.d.ts +2 -0
  6. package/dist/cjs/Viewport.js +2 -0
  7. package/dist/cjs/components/AbstractComponent.d.ts +9 -0
  8. package/dist/cjs/components/AbstractComponent.js +11 -0
  9. package/dist/cjs/components/Stroke.d.ts +3 -0
  10. package/dist/cjs/components/Stroke.js +55 -1
  11. package/dist/cjs/image/EditorImage.js +17 -1
  12. package/dist/cjs/rendering/RenderablePathSpec.d.ts +20 -2
  13. package/dist/cjs/rendering/RenderablePathSpec.js +72 -9
  14. package/dist/cjs/rendering/caching/CacheRecord.js +5 -3
  15. package/dist/cjs/rendering/renderers/AbstractRenderer.d.ts +10 -0
  16. package/dist/cjs/rendering/renderers/AbstractRenderer.js +12 -3
  17. package/dist/cjs/rendering/renderers/CanvasRenderer.js +2 -2
  18. package/dist/cjs/rendering/renderers/SVGRenderer.d.ts +0 -10
  19. package/dist/cjs/rendering/renderers/SVGRenderer.js +0 -14
  20. package/dist/cjs/testing/startPinchGesture.d.ts +14 -0
  21. package/dist/cjs/testing/startPinchGesture.js +41 -0
  22. package/dist/cjs/tools/PanZoom.d.ts +4 -0
  23. package/dist/cjs/tools/PanZoom.js +21 -2
  24. package/dist/cjs/version.js +1 -1
  25. package/dist/mjs/EventDispatcher.mjs +2 -1
  26. package/dist/mjs/Viewport.d.ts +2 -0
  27. package/dist/mjs/Viewport.mjs +2 -0
  28. package/dist/mjs/components/AbstractComponent.d.ts +9 -0
  29. package/dist/mjs/components/AbstractComponent.mjs +11 -0
  30. package/dist/mjs/components/Stroke.d.ts +3 -0
  31. package/dist/mjs/components/Stroke.mjs +56 -2
  32. package/dist/mjs/image/EditorImage.mjs +17 -1
  33. package/dist/mjs/rendering/RenderablePathSpec.d.ts +20 -2
  34. package/dist/mjs/rendering/RenderablePathSpec.mjs +71 -9
  35. package/dist/mjs/rendering/caching/CacheRecord.mjs +5 -3
  36. package/dist/mjs/rendering/renderers/AbstractRenderer.d.ts +10 -0
  37. package/dist/mjs/rendering/renderers/AbstractRenderer.mjs +12 -3
  38. package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +2 -2
  39. package/dist/mjs/rendering/renderers/SVGRenderer.d.ts +0 -10
  40. package/dist/mjs/rendering/renderers/SVGRenderer.mjs +0 -14
  41. package/dist/mjs/testing/startPinchGesture.d.ts +14 -0
  42. package/dist/mjs/testing/startPinchGesture.mjs +36 -0
  43. package/dist/mjs/tools/PanZoom.d.ts +4 -0
  44. package/dist/mjs/tools/PanZoom.mjs +21 -2
  45. package/dist/mjs/version.mjs +1 -1
  46. package/package.json +3 -3
  47. package/src/Editor.scss +2 -0
@@ -36,7 +36,6 @@ export default class SVGRenderer extends AbstractRenderer {
36
36
  this.textContainer = null;
37
37
  this.textContainerTransform = null;
38
38
  this.textParentStyle = defaultTextStyle;
39
- this.visibleRectOverride = null;
40
39
  this.clear();
41
40
  this.addStyleSheet();
42
41
  }
@@ -339,19 +338,6 @@ export default class SVGRenderer extends AbstractRenderer {
339
338
  isTooSmallToRender(_rect) {
340
339
  return false;
341
340
  }
342
- /**
343
- * Overrides the visible region returned by `getVisibleRect`.
344
- *
345
- * This is useful when the `viewport`'s transform has been modified,
346
- * for example, to compensate for storing part of the image's
347
- * transformation in an SVG property.
348
- */
349
- overrideVisibleRect(newRect) {
350
- this.visibleRectOverride = newRect;
351
- }
352
- getVisibleRect() {
353
- return this.visibleRectOverride ?? super.getVisibleRect();
354
- }
355
341
  /**
356
342
  * Creates a new SVG element and `SVGRenerer` with `width`, `height`, `viewBox`,
357
343
  * and other metadata attributes set for the given `Viewport`.
@@ -0,0 +1,14 @@
1
+ import type Editor from '../Editor';
2
+ import { Point2 } from '@js-draw/math';
3
+ /**
4
+ * Creates two pointers and sends the touch {@link InputEvtType.PointerDownEvt}s for them.
5
+ *
6
+ * Returns an object that allows continuing or ending the gesture.
7
+ *
8
+ * `initialRotation` should be in radians.
9
+ */
10
+ declare const startPinchGesture: (editor: Editor, center: Point2, initialDistance: number, initialRotation: number) => {
11
+ update(center: Point2, distance: number, rotation: number): void;
12
+ end(): void;
13
+ };
14
+ export default startPinchGesture;
@@ -0,0 +1,36 @@
1
+ import { Mat33, Vec2 } from '@js-draw/math';
2
+ import sendTouchEvent from './sendTouchEvent.mjs';
3
+ import { InputEvtType } from '../inputEvents.mjs';
4
+ /**
5
+ * Creates two pointers and sends the touch {@link InputEvtType.PointerDownEvt}s for them.
6
+ *
7
+ * Returns an object that allows continuing or ending the gesture.
8
+ *
9
+ * `initialRotation` should be in radians.
10
+ */
11
+ const startPinchGesture = (editor, center, initialDistance, initialRotation) => {
12
+ const computeTouchPoints = (center, distance, rotation) => {
13
+ const halfDisplacement = Mat33.zRotation(rotation).transformVec2(Vec2.of(0, distance / 2));
14
+ const point1 = center.plus(halfDisplacement);
15
+ const point2 = center.minus(halfDisplacement);
16
+ return [point1, point2];
17
+ };
18
+ let [touchPoint1, touchPoint2] = computeTouchPoints(center, initialDistance, initialRotation);
19
+ let firstPointer = sendTouchEvent(editor, InputEvtType.PointerDownEvt, touchPoint1);
20
+ let secondPointer = sendTouchEvent(editor, InputEvtType.PointerDownEvt, touchPoint2, [firstPointer]);
21
+ return {
22
+ update(center, distance, rotation) {
23
+ const eventType = InputEvtType.PointerMoveEvt;
24
+ const [newPoint1, newPoint2] = computeTouchPoints(center, distance, rotation);
25
+ touchPoint1 = newPoint1;
26
+ touchPoint2 = newPoint2;
27
+ firstPointer = sendTouchEvent(editor, eventType, newPoint1, [secondPointer]);
28
+ secondPointer = sendTouchEvent(editor, eventType, newPoint2, [firstPointer]);
29
+ },
30
+ end() {
31
+ sendTouchEvent(editor, InputEvtType.PointerUpEvt, touchPoint1, [secondPointer]);
32
+ sendTouchEvent(editor, InputEvtType.PointerUpEvt, touchPoint2);
33
+ },
34
+ };
35
+ };
36
+ export default startPinchGesture;
@@ -21,6 +21,9 @@ export default class PanZoom extends BaseTool {
21
21
  private editor;
22
22
  private mode;
23
23
  private transform;
24
+ private readonly initialRotationSnapAngle;
25
+ private readonly afterRotationStartSnapAngle;
26
+ private readonly pinchZoomStartThreshold;
24
27
  private startDist;
25
28
  private lastDist;
26
29
  private lastScreenCenter;
@@ -29,6 +32,7 @@ export default class PanZoom extends BaseTool {
29
32
  private initialTouchAngle;
30
33
  private initialViewportRotation;
31
34
  private isScaling;
35
+ private isRotating;
32
36
  private inertialScroller;
33
37
  private velocity;
34
38
  constructor(editor: Editor, mode: PanZoomMode, description: string);
@@ -65,12 +65,19 @@ export default class PanZoom extends BaseTool {
65
65
  this.editor = editor;
66
66
  this.mode = mode;
67
67
  this.transform = null;
68
+ // Constants
69
+ // initialRotationSnapAngle is larger than afterRotationStartSnapAngle to
70
+ // make it more difficult to start rotating (and easier to continue rotating).
71
+ this.initialRotationSnapAngle = 0.22; // radians
72
+ this.afterRotationStartSnapAngle = 0.07; // radians
73
+ this.pinchZoomStartThreshold = 1.08; // scale factor
68
74
  this.lastPointerDownTimestamp = 0;
69
75
  this.initialTouchAngle = 0;
70
76
  this.initialViewportRotation = 0;
71
77
  // Set to `true` only when scaling has started (if two fingers are down and have moved
72
78
  // far enough).
73
79
  this.isScaling = false;
80
+ this.isRotating = false;
74
81
  this.inertialScroller = null;
75
82
  this.velocity = null;
76
83
  }
@@ -112,6 +119,9 @@ export default class PanZoom extends BaseTool {
112
119
  this.initialTouchAngle = angle;
113
120
  this.initialViewportRotation = this.editor.viewport.getRotationAngle();
114
121
  this.isScaling = false;
122
+ // We're initially rotated if `initialViewportRotation` isn't near a multiple of pi/2.
123
+ // In other words, if sin(2 initialViewportRotation) is near zero.
124
+ this.isRotating = Math.abs(Math.sin(this.initialViewportRotation * 2)) > 1e-3;
115
125
  handlingGesture = true;
116
126
  }
117
127
  else if (pointers.length === 1 && ((this.mode & PanZoomMode.OneFingerTouchGestures && allAreTouch)
@@ -168,7 +178,9 @@ export default class PanZoom extends BaseTool {
168
178
  const roundedFullRotation = Math.round(fullRotation / snapToMultipleOf) * snapToMultipleOf;
169
179
  // The maximum angle for which we snap the given angle to a multiple of
170
180
  // `snapToMultipleOf`.
171
- const maxSnapAngle = 0.07;
181
+ // Use a smaller snap angle if already rotated (to avoid pinch zoom gestures from
182
+ // starting rotation).
183
+ const maxSnapAngle = this.isRotating ? this.afterRotationStartSnapAngle : this.initialRotationSnapAngle;
172
184
  // Snap the rotation
173
185
  if (Math.abs(fullRotation - roundedFullRotation) < maxSnapAngle) {
174
186
  fullRotation = roundedFullRotation;
@@ -191,6 +203,11 @@ export default class PanZoom extends BaseTool {
191
203
  else {
192
204
  deltaRotation = this.toSnappedRotationDelta(angle);
193
205
  }
206
+ // If any rotation, make a note of this (affects rotation snap
207
+ // angles).
208
+ if (Math.abs(deltaRotation) > 1e-8) {
209
+ this.isRotating = true;
210
+ }
194
211
  this.updateVelocity(screenCenter);
195
212
  let scaleFactor = 1;
196
213
  if (this.isScaling) {
@@ -199,7 +216,9 @@ export default class PanZoom extends BaseTool {
199
216
  else {
200
217
  const initialScaleFactor = dist / this.startDist;
201
218
  // Only start scaling if scaling done so far exceeds some threshold.
202
- if (initialScaleFactor > 1.05 || initialScaleFactor < 0.95) {
219
+ const upperBound = this.pinchZoomStartThreshold;
220
+ const lowerBound = 1 / this.pinchZoomStartThreshold;
221
+ if (initialScaleFactor > upperBound || initialScaleFactor < lowerBound) {
203
222
  scaleFactor = initialScaleFactor;
204
223
  this.isScaling = true;
205
224
  }
@@ -1,3 +1,3 @@
1
1
  export default {
2
- number: '1.7.2',
2
+ number: '1.8.0',
3
3
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-draw",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
5
5
  "types": "./dist/mjs/lib.d.ts",
6
6
  "main": "./dist/cjs/lib.js",
@@ -64,7 +64,7 @@
64
64
  "postpack": "ts-node tools/copyREADME.ts revert"
65
65
  },
66
66
  "dependencies": {
67
- "@js-draw/math": "^1.7.0",
67
+ "@js-draw/math": "^1.8.0",
68
68
  "@melloware/coloris": "0.21.0"
69
69
  },
70
70
  "devDependencies": {
@@ -86,5 +86,5 @@
86
86
  "freehand",
87
87
  "svg"
88
88
  ],
89
- "gitHead": "e1677b6e40bd385e1ce40643fd10f064847adf5b"
89
+ "gitHead": "89f7991833dec5c17ce0890321286198ff7b1900"
90
90
  }
package/src/Editor.scss CHANGED
@@ -118,6 +118,8 @@
118
118
  text-align: center;
119
119
  font-size: 2em;
120
120
 
121
+ text-shadow: 0px 0px 1px var(--background-color-1);
122
+
121
123
  bottom: 0;
122
124
  left: 0;
123
125
  right: 0;