@zoompinch/core 0.0.28 → 0.0.31
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/dist/helpers.d.ts +10 -0
- package/dist/zoompinch-core.es.js +55 -65
- package/dist/zoompinch-core.umd.js +1 -1
- package/dist/zoompinch.d.ts +1 -0
- package/package.json +1 -1
package/dist/helpers.d.ts
CHANGED
|
@@ -9,6 +9,16 @@ export declare function rotateVector(vector: [number, number], angle: number): [
|
|
|
9
9
|
export declare function moveAlongVector(startPoint: [number, number], vector: [number, number], length: number): [number, number];
|
|
10
10
|
export declare function round(value: number, decimals: number): number;
|
|
11
11
|
export declare function detectTrackpad(event: WheelEvent): boolean;
|
|
12
|
+
export declare function normalizeWheelDelta(event: WheelEvent): {
|
|
13
|
+
deltaX: number;
|
|
14
|
+
deltaY: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function normalizeWheel(event: WheelEvent): {
|
|
17
|
+
spinX: number;
|
|
18
|
+
spinY: number;
|
|
19
|
+
pixelX: number;
|
|
20
|
+
pixelY: number;
|
|
21
|
+
};
|
|
12
22
|
export declare function isMultipleOf(n: number, multiples: number[]): number;
|
|
13
23
|
export declare function getUntransformedRect(rect: DOMRect, tx: number, ty: number, scale: number, rotate: number): {
|
|
14
24
|
x: number;
|
|
@@ -1,59 +1,49 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
function
|
|
5
|
-
return
|
|
1
|
+
var P = Object.defineProperty;
|
|
2
|
+
var z = (h, l, t) => l in h ? P(h, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[l] = t;
|
|
3
|
+
var d = (h, l, t) => z(h, typeof l != "symbol" ? l + "" : l, t);
|
|
4
|
+
function F(h) {
|
|
5
|
+
return h * Math.PI / 180;
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
return Math.min(Math.max(
|
|
7
|
+
function B(h, l, t) {
|
|
8
|
+
return Math.min(Math.max(h, l), t);
|
|
9
9
|
}
|
|
10
|
-
function
|
|
11
|
-
const [e, s] =
|
|
10
|
+
function v(h, l, t) {
|
|
11
|
+
const [e, s] = h, [a, n] = l, r = Math.cos(t) * (e - a) - Math.sin(t) * (s - n) + a, i = Math.sin(t) * (e - a) + Math.cos(t) * (s - n) + n;
|
|
12
12
|
return [r, i];
|
|
13
13
|
}
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
function I(o) {
|
|
19
|
-
if (o.ctrlKey) {
|
|
20
|
-
const { deltaY: t, deltaMode: e, ctrlKey: s } = o, a = Math.abs(t), n = a === 120 || a === 100 || a === 3, r = t % 1 !== 0, i = e === 0;
|
|
14
|
+
function I(h) {
|
|
15
|
+
if (h.ctrlKey) {
|
|
16
|
+
const { deltaY: t, deltaMode: e, ctrlKey: s } = h, a = Math.abs(t), n = a === 120 || a === 100 || a === 3, r = t % 1 !== 0, i = e === 0;
|
|
21
17
|
return s ? a < 50 && i || r : !n && (r || i && a < 50);
|
|
22
18
|
} else {
|
|
23
19
|
var l = !1;
|
|
24
|
-
return
|
|
20
|
+
return h.wheelDeltaY ? h.wheelDeltaY === h.deltaY * -3 && (l = !0) : h.deltaMode === 0 && (l = !0), l;
|
|
25
21
|
}
|
|
26
22
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const r = Math.cos(-s), i = Math.sin(-s);
|
|
30
|
-
let c = a * r - n * i, h = a * i + n * r;
|
|
31
|
-
const d = o.width / e, p = o.height / e;
|
|
32
|
-
return c /= e, h /= e, { x: Y(c, 4), y: Y(h, 4), width: Y(d, 4), height: Y(p, 4) };
|
|
33
|
-
}
|
|
34
|
-
class D extends EventTarget {
|
|
35
|
-
constructor(t, e, s, a, n, r, i = 0.1, c = 10, h = !1, d = !0) {
|
|
23
|
+
class x extends EventTarget {
|
|
24
|
+
constructor(t, e, s, a, n, r, i = 0.1, c = 10, o = !1, u = !0) {
|
|
36
25
|
super();
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this
|
|
26
|
+
d(this, "wrapperBounds");
|
|
27
|
+
d(this, "canvasBounds");
|
|
28
|
+
d(this, "translateSpeed", 1);
|
|
29
|
+
d(this, "zoomSpeed", 1);
|
|
30
|
+
d(this, "translateSpeedAppleTrackpad", 1);
|
|
31
|
+
d(this, "zoomSpeedAppleTrackpad", 1);
|
|
32
|
+
d(this, "isGestureActive", !1);
|
|
33
|
+
d(this, "gestureStartRotate", 0);
|
|
34
|
+
d(this, "dragStart", null);
|
|
35
|
+
d(this, "dragStartFrozenX", null);
|
|
36
|
+
d(this, "dragStartFrozenY", null);
|
|
37
|
+
d(this, "touchStarts", null);
|
|
38
|
+
d(this, "touchStartTranslateX", 0);
|
|
39
|
+
d(this, "touchStartTranslateY", 0);
|
|
40
|
+
this.element = t, this.offset = e, this.translateX = s, this.translateY = a, this.scale = n, this.rotate = r, this.minScale = i, this.maxScale = c, this.clampBounds = o, this.rotation = u;
|
|
51
41
|
const p = new ResizeObserver(() => {
|
|
52
|
-
const { x: g, y: m, width: S, height:
|
|
53
|
-
this.wrapperBounds = { x: g, y: m, width: S, height:
|
|
54
|
-
}), f = new ResizeObserver(() => {
|
|
55
|
-
const {
|
|
56
|
-
this.canvasBounds
|
|
42
|
+
const { x: g, y: m, width: S, height: Y } = this.element.getBoundingClientRect();
|
|
43
|
+
this.wrapperBounds = { x: g, y: m, width: S, height: Y }, this.update();
|
|
44
|
+
}), f = new ResizeObserver((g) => {
|
|
45
|
+
const { width: m, height: S } = g[0].contentRect;
|
|
46
|
+
(m !== this.canvasBounds.width || S !== this.canvasBounds.height) && (this.canvasBounds = { ...this.canvasBounds, width: m, height: S }, this.isGestureActive || this.update());
|
|
57
47
|
});
|
|
58
48
|
requestAnimationFrame(() => {
|
|
59
49
|
this.wrapperBounds = this.element.getBoundingClientRect(), this.canvasBounds = this.canvasElement.getBoundingClientRect(), this.update(), this.dispatchEvent(new Event("init"));
|
|
@@ -102,7 +92,7 @@ class D extends EventTarget {
|
|
|
102
92
|
if (a === 0 || !this.rotation)
|
|
103
93
|
return;
|
|
104
94
|
const n = this.normalizeClientCoords(e, s);
|
|
105
|
-
this.rotateCanvas(n[0], n[1], this.gestureStartRotate +
|
|
95
|
+
this.rotateCanvas(n[0], n[1], this.gestureStartRotate + F(a));
|
|
106
96
|
}
|
|
107
97
|
handleGestureend(t) {
|
|
108
98
|
}
|
|
@@ -125,13 +115,13 @@ class D extends EventTarget {
|
|
|
125
115
|
const r = this.scale;
|
|
126
116
|
if (a) {
|
|
127
117
|
const i = n ? 0.01 * this.zoomSpeedAppleTrackpad : 0.1 * this.zoomSpeed, c = 1 + -s * i;
|
|
128
|
-
let
|
|
129
|
-
if (
|
|
118
|
+
let o = r * c;
|
|
119
|
+
if (o = B(o, this.minScale, this.maxScale), (o === this.minScale || o === this.maxScale) && (o === this.minScale && c < 1 || o === this.maxScale && c > 1)) {
|
|
130
120
|
t.preventDefault();
|
|
131
121
|
return;
|
|
132
122
|
}
|
|
133
|
-
const
|
|
134
|
-
this.setTranslateFromUserGesture(p, f), this.scale =
|
|
123
|
+
const u = this.relativeWrapperCoordinatesFromClientCoords(t.clientX, t.clientY), [p, f] = this.calcProjectionTranslate(o, u, this.normalizeMatrixCoordinates(t.clientX, t.clientY));
|
|
124
|
+
this.setTranslateFromUserGesture(p, f), this.scale = o;
|
|
135
125
|
} else {
|
|
136
126
|
const i = n ? 1 * this.translateSpeedAppleTrackpad : 25 * this.translateSpeed;
|
|
137
127
|
this.setTranslateFromUserGesture(this.translateX - e * i, this.translateY - s * i);
|
|
@@ -148,22 +138,22 @@ class D extends EventTarget {
|
|
|
148
138
|
});
|
|
149
139
|
}
|
|
150
140
|
handleTouchstart(t) {
|
|
151
|
-
this.touchStarts = this.freezeTouches(t.touches), this.touchStartTranslateX = this.translateX, this.touchStartTranslateY = this.translateY, t.preventDefault();
|
|
141
|
+
this.touchStarts = this.freezeTouches(t.touches), this.touchStartTranslateX = this.translateX, this.touchStartTranslateY = this.translateY, this.isGestureActive = !0, t.preventDefault();
|
|
152
142
|
}
|
|
153
143
|
handleTouchmove(t) {
|
|
154
144
|
t.preventDefault();
|
|
155
145
|
const e = Array.from(t.touches).map((s) => this.clientCoordsToWrapperCoords(s.clientX, s.clientY));
|
|
156
146
|
if (this.touchStarts) {
|
|
157
147
|
if (e.length >= 2 && this.touchStarts.length >= 2) {
|
|
158
|
-
const s = [this.touchStarts[0].canvasRel[0] * this.canvasBounds.width, this.touchStarts[0].canvasRel[1] * this.canvasBounds.height], a = [this.touchStarts[1].canvasRel[0] * this.canvasBounds.width, this.touchStarts[1].canvasRel[1] * this.canvasBounds.height], n = Math.sqrt(Math.pow(s[0] - a[0], 2) + Math.pow(s[1] - a[1], 2)), r = Math.sqrt(Math.pow(e[0][0] - e[1][0], 2) + Math.pow(e[0][1] - e[1][1], 2)) / this.naturalScale, i =
|
|
148
|
+
const s = [this.touchStarts[0].canvasRel[0] * this.canvasBounds.width, this.touchStarts[0].canvasRel[1] * this.canvasBounds.height], a = [this.touchStarts[1].canvasRel[0] * this.canvasBounds.width, this.touchStarts[1].canvasRel[1] * this.canvasBounds.height], n = Math.sqrt(Math.pow(s[0] - a[0], 2) + Math.pow(s[1] - a[1], 2)), r = Math.sqrt(Math.pow(e[0][0] - e[1][0], 2) + Math.pow(e[0][1] - e[1][1], 2)) / this.naturalScale, i = B(r / n, this.minScale, this.maxScale), c = [e[0][0] / this.wrapperInnerWidth, e[0][1] / this.wrapperInnerHeight], o = this.touchStarts[0].canvasRel, [u, p] = this.calcProjectionTranslate(i, c, o, 0);
|
|
159
149
|
if (this.rotation) {
|
|
160
150
|
let f = 0, g = 0, m = 0;
|
|
161
151
|
const S = Math.atan2(a[1] - s[1], a[0] - s[0]);
|
|
162
152
|
m = Math.atan2(e[1][1] - e[0][1], e[1][0] - e[0][0]) - S;
|
|
163
|
-
const
|
|
164
|
-
f =
|
|
153
|
+
const X = (R, M) => [this.offset.left + this.canvasBounds.width * R * this.naturalScale * i + u, this.offset.top + this.canvasBounds.height * M * this.naturalScale * i + p], w = X(0, 0), C = X(this.touchStarts[0].canvasRel[0], this.touchStarts[0].canvasRel[1]), T = v(w, C, m);
|
|
154
|
+
f = T[0] - w[0], g = T[1] - w[1], this.scale = i, this.rotate = m, this.setTranslateFromUserGesture(u + f, p + g);
|
|
165
155
|
} else
|
|
166
|
-
this.scale = i, this.setTranslateFromUserGesture(
|
|
156
|
+
this.scale = i, this.setTranslateFromUserGesture(u, p);
|
|
167
157
|
} else {
|
|
168
158
|
const s = t.touches[0].clientX - this.touchStarts[0].client[0], a = t.touches[0].clientY - this.touchStarts[0].client[1], n = this.touchStartTranslateX + s, r = this.touchStartTranslateY + a;
|
|
169
159
|
this.setTranslateFromUserGesture(n, r);
|
|
@@ -172,10 +162,10 @@ class D extends EventTarget {
|
|
|
172
162
|
}
|
|
173
163
|
}
|
|
174
164
|
handleTouchend(t) {
|
|
175
|
-
t.touches.length === 0 ? this.touchStarts = null : (this.touchStarts = this.freezeTouches(t.touches), this.touchStartTranslateX = this.translateX, this.touchStartTranslateY = this.translateY);
|
|
165
|
+
t.touches.length === 0 ? this.touchStarts = null : (this.touchStarts = this.freezeTouches(t.touches), this.touchStartTranslateX = this.translateX, this.touchStartTranslateY = this.translateY), this.isGestureActive = !1;
|
|
176
166
|
}
|
|
177
167
|
calcProjectionTranslate(t, e, s, a) {
|
|
178
|
-
const n = this.canvasBounds.width * this.naturalScale, r = this.canvasBounds.height * this.naturalScale, i = s[0] * n * t, c = s[1] * r * t,
|
|
168
|
+
const n = this.canvasBounds.width * this.naturalScale, r = this.canvasBounds.height * this.naturalScale, i = s[0] * n * t, c = s[1] * r * t, o = v([i, c], [0, 0], a ?? this.rotate), u = e[0] * this.wrapperInnerWidth, p = e[1] * this.wrapperInnerHeight, f = u - o[0], g = p - o[1];
|
|
179
169
|
return [f, g];
|
|
180
170
|
}
|
|
181
171
|
applyTransform(t, e, s) {
|
|
@@ -184,8 +174,8 @@ class D extends EventTarget {
|
|
|
184
174
|
}
|
|
185
175
|
composeRelPoint(t, e, s, a, n, r) {
|
|
186
176
|
s = s ?? this.scale, a = a ?? this.translateX, n = n ?? this.translateY, r = r ?? this.rotate;
|
|
187
|
-
const i = [this.offset.left, this.offset.top], c = [this.offset.left + this.canvasBounds.width * (s * this.naturalScale) * t, this.offset.top + this.canvasBounds.height * (s * this.naturalScale) * e],
|
|
188
|
-
return [
|
|
177
|
+
const i = [this.offset.left, this.offset.top], c = [this.offset.left + this.canvasBounds.width * (s * this.naturalScale) * t, this.offset.top + this.canvasBounds.height * (s * this.naturalScale) * e], o = v(c, i, r);
|
|
178
|
+
return [o[0] + a, o[1] + n];
|
|
189
179
|
}
|
|
190
180
|
composePoint(t, e) {
|
|
191
181
|
const s = t / this.canvasBounds.width, a = e / this.canvasBounds.height;
|
|
@@ -195,12 +185,12 @@ class D extends EventTarget {
|
|
|
195
185
|
const r = this.calcProjectionTranslate(t, n, n, 0), i = [
|
|
196
186
|
this.offset.left + r[0] + this.canvasBounds.width * (t * this.naturalScale) * n[0],
|
|
197
187
|
this.offset.top + r[1] + this.canvasBounds.height * (t * this.naturalScale) * n[1]
|
|
198
|
-
], c = this.composeRelPoint(n[0], n[1], t, e, s, a),
|
|
199
|
-
return [
|
|
188
|
+
], c = this.composeRelPoint(n[0], n[1], t, e, s, a), o = c[0] - i[0], u = c[1] - i[1];
|
|
189
|
+
return [o, u];
|
|
200
190
|
}
|
|
201
191
|
// Converts absolute inner wrapper coordinates to relative canvas coordinates (0-1, 0-1)
|
|
202
192
|
getCanvasCoordsRel(t, e) {
|
|
203
|
-
const s = [0, 0], a = [t - this.translateX, e - this.translateY], n =
|
|
193
|
+
const s = [0, 0], a = [t - this.translateX, e - this.translateY], n = v(a, s, -this.rotate), r = [n[0] / this.renderinScale, n[1] / this.renderinScale];
|
|
204
194
|
return [r[0] / this.canvasBounds.width, r[1] / this.canvasBounds.height];
|
|
205
195
|
}
|
|
206
196
|
// Converts absolute client to coordinates to absolute inner-wrapper coorinates
|
|
@@ -239,10 +229,10 @@ class D extends EventTarget {
|
|
|
239
229
|
return this.rotate;
|
|
240
230
|
}
|
|
241
231
|
clampTranslate(t, e = [0.5, 0.5]) {
|
|
242
|
-
const s = this.canvasBounds.width * this.naturalScale * t.scale, a = this.canvasBounds.height * this.naturalScale * t.scale, n = s - this.wrapperInnerWidth, r = a - this.wrapperInnerHeight, i = n > 0 ? -n : 0, c = Math.min(0, Math.max(t.translateX, i)),
|
|
232
|
+
const s = this.canvasBounds.width * this.naturalScale * t.scale, a = this.canvasBounds.height * this.naturalScale * t.scale, n = s - this.wrapperInnerWidth, r = a - this.wrapperInnerHeight, i = n > 0 ? -n : 0, c = Math.min(0, Math.max(t.translateX, i)), o = r > 0 ? -r : 0, u = Math.min(0, Math.max(t.translateY, o)), p = -Math.min(0, n) * e[0], f = -Math.min(0, r) * e[1];
|
|
243
233
|
return {
|
|
244
234
|
translateX: c + p,
|
|
245
|
-
translateY:
|
|
235
|
+
translateY: u + f
|
|
246
236
|
};
|
|
247
237
|
}
|
|
248
238
|
update() {
|
|
@@ -252,5 +242,5 @@ class D extends EventTarget {
|
|
|
252
242
|
}
|
|
253
243
|
}
|
|
254
244
|
export {
|
|
255
|
-
|
|
245
|
+
x as Zoompinch
|
|
256
246
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(f,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(f=typeof globalThis<"u"?globalThis:f||self,u(f.Zoompinch={}))})(this,(function(f){"use strict";var W=Object.defineProperty;var D=(f,u,v)=>u in f?W(f,u,{enumerable:!0,configurable:!0,writable:!0,value:v}):f[u]=v;var d=(f,u,v)=>D(f,typeof u!="symbol"?u+"":u,v);function u(h){return h*Math.PI/180}function v(h,g,t){return Math.min(Math.max(h,g),t)}function T(h,g,t){const[e,s]=h,[a,n]=g,r=Math.cos(t)*(e-a)-Math.sin(t)*(s-n)+a,i=Math.sin(t)*(e-a)+Math.cos(t)*(s-n)+n;return[r,i]}function X(h,g){const t=Math.pow(10,g);return Math.round(h*t)/t}function P(h){if(h.ctrlKey){const{deltaY:t,deltaMode:e,ctrlKey:s}=h,a=Math.abs(t),n=a===120||a===100||a===3,r=t%1!==0,i=e===0;return s?a<50&&i||r:!n&&(r||i&&a<50)}else{var g=!1;return h.wheelDeltaY?h.wheelDeltaY===h.deltaY*-3&&(g=!0):h.deltaMode===0&&(g=!0),g}}function z(h,g,t,e,s){let a=h.left-g,n=h.top-t;const r=Math.cos(-s),i=Math.sin(-s);let l=a*r-n*i,o=a*i+n*r;const c=h.width/e,p=h.height/e;return l/=e,o/=e,{x:X(l,4),y:X(o,4),width:X(c,4),height:X(p,4)}}class F extends EventTarget{constructor(t,e,s,a,n,r,i=.1,l=10,o=!1,c=!0){super();d(this,"wrapperBounds");d(this,"canvasBounds");d(this,"translateSpeed",1);d(this,"zoomSpeed",1);d(this,"translateSpeedAppleTrackpad",1);d(this,"zoomSpeedAppleTrackpad",1);d(this,"gestureStartRotate",0);d(this,"dragStart",null);d(this,"dragStartFrozenX",null);d(this,"dragStartFrozenY",null);d(this,"touchStarts",null);d(this,"touchStartTranslateX",0);d(this,"touchStartTranslateY",0);this.element=t,this.offset=e,this.translateX=s,this.translateY=a,this.scale=n,this.rotate=r,this.minScale=i,this.maxScale=l,this.clampBounds=o,this.rotation=c;const p=new ResizeObserver(()=>{const{x:S,y:w,width:Y,height:R}=this.element.getBoundingClientRect();this.wrapperBounds={x:S,y:w,width:Y,height:R},this.update()}),m=new ResizeObserver(()=>{const{x:S,y:w,width:Y,height:R}=z(this.canvasElement.getBoundingClientRect(),this.renderingTranslateX,this.renderingTranslateY,this.renderinScale,this.renderingRotate);this.canvasBounds={x:S,y:w,width:Y,height:R},this.update()});requestAnimationFrame(()=>{this.wrapperBounds=this.element.getBoundingClientRect(),this.canvasBounds=this.canvasElement.getBoundingClientRect(),this.update(),this.dispatchEvent(new Event("init"))}),m.observe(this.canvasElement),p.observe(this.element)}get canvasElement(){return this.element.querySelector(".canvas")}get wrapperInnerX(){return this.wrapperBounds.x+this.offset.left}get wrapperInnerY(){return this.wrapperBounds.y+this.offset.top}get wrapperInnerWidth(){return this.wrapperBounds.width-this.offset.left-this.offset.right}get wrapperInnerHeight(){return this.wrapperBounds.height-this.offset.top-this.offset.bottom}get wrapperInnerRatio(){return this.wrapperInnerWidth/this.wrapperInnerHeight}get canvasNaturalRatio(){return this.canvasBounds.width/this.canvasBounds.height}get naturalScale(){return this.canvasNaturalRatio>=this.wrapperInnerRatio?this.wrapperInnerWidth/this.canvasBounds.width:this.wrapperInnerHeight/this.canvasBounds.height}setTranslateFromUserGesture(t,e){if(this.clampBounds){const s=this.clampTranslate({translateX:t,translateY:e,scale:this.scale,rotate:this.rotate});this.translateX=s.translateX,this.translateY=s.translateY,this.rotate=0}else this.translateX=t,this.translateY=e}handleGesturestart(t){this.gestureStartRotate=this.rotate}handleGesturechange(t){const{clientX:e,clientY:s}=t,a=t.rotation;if(a===0||!this.rotation)return;const n=this.normalizeClientCoords(e,s);this.rotateCanvas(n[0],n[1],this.gestureStartRotate+u(a))}handleGestureend(t){}handleMousedown(t){t.preventDefault(),this.dragStart=[t.clientX,t.clientY],this.dragStartFrozenX=this.translateX,this.dragStartFrozenY=this.translateY}handleMouseup(t){t.preventDefault(),this.dragStart=null,this.dragStartFrozenX=null,this.dragStartFrozenY=null}handleMousemove(t){if(t.preventDefault(),this.dragStart&&this.dragStartFrozenX!==null&&this.dragStartFrozenY!==null){const e=t.clientX-this.dragStart[0],s=t.clientY-this.dragStart[1],a=this.dragStartFrozenX- -e,n=this.dragStartFrozenY- -s;this.setTranslateFromUserGesture(a,n),this.update()}}handleWheel(t){let{deltaX:e,deltaY:s,ctrlKey:a}=t;const n=P(t);n||(Math.abs(s)>=100&&(s=Math.sign(s)*(Math.abs(s)/120)),Math.abs(e)>=100&&(e=Math.sign(e)*(Math.abs(e)/120)));const r=this.scale;if(a){const i=n?.01*this.zoomSpeedAppleTrackpad:.1*this.zoomSpeed,l=1+-s*i;let o=r*l;if(o=v(o,this.minScale,this.maxScale),(o===this.minScale||o===this.maxScale)&&(o===this.minScale&&l<1||o===this.maxScale&&l>1)){t.preventDefault();return}const c=this.relativeWrapperCoordinatesFromClientCoords(t.clientX,t.clientY),[p,m]=this.calcProjectionTranslate(o,c,this.normalizeMatrixCoordinates(t.clientX,t.clientY));this.setTranslateFromUserGesture(p,m),this.scale=o}else{const i=n?1*this.translateSpeedAppleTrackpad:25*this.translateSpeed;this.setTranslateFromUserGesture(this.translateX-e*i,this.translateY-s*i)}this.update(),t.preventDefault()}freezeTouches(t){return Array.from(t).map(e=>{const s=this.clientCoordsToWrapperCoords(e.clientX,e.clientY);return{client:[e.clientX,e.clientY],canvasRel:this.getCanvasCoordsRel(s[0],s[1])}})}handleTouchstart(t){this.touchStarts=this.freezeTouches(t.touches),this.touchStartTranslateX=this.translateX,this.touchStartTranslateY=this.translateY,t.preventDefault()}handleTouchmove(t){t.preventDefault();const e=Array.from(t.touches).map(s=>this.clientCoordsToWrapperCoords(s.clientX,s.clientY));if(this.touchStarts){if(e.length>=2&&this.touchStarts.length>=2){const s=[this.touchStarts[0].canvasRel[0]*this.canvasBounds.width,this.touchStarts[0].canvasRel[1]*this.canvasBounds.height],a=[this.touchStarts[1].canvasRel[0]*this.canvasBounds.width,this.touchStarts[1].canvasRel[1]*this.canvasBounds.height],n=Math.sqrt(Math.pow(s[0]-a[0],2)+Math.pow(s[1]-a[1],2)),r=Math.sqrt(Math.pow(e[0][0]-e[1][0],2)+Math.pow(e[0][1]-e[1][1],2))/this.naturalScale,i=v(r/n,this.minScale,this.maxScale),l=[e[0][0]/this.wrapperInnerWidth,e[0][1]/this.wrapperInnerHeight],o=this.touchStarts[0].canvasRel,[c,p]=this.calcProjectionTranslate(i,l,o,0);if(this.rotation){let m=0,S=0,w=0;const Y=Math.atan2(a[1]-s[1],a[0]-s[0]);w=Math.atan2(e[1][1]-e[0][1],e[1][0]-e[0][0])-Y;const M=(y,I)=>[this.offset.left+this.canvasBounds.width*y*this.naturalScale*i+c,this.offset.top+this.canvasBounds.height*I*this.naturalScale*i+p],C=M(0,0),x=M(this.touchStarts[0].canvasRel[0],this.touchStarts[0].canvasRel[1]),B=T(C,x,w);m=B[0]-C[0],S=B[1]-C[1],this.scale=i,this.rotate=w,this.setTranslateFromUserGesture(c+m,p+S)}else this.scale=i,this.setTranslateFromUserGesture(c,p)}else{const s=t.touches[0].clientX-this.touchStarts[0].client[0],a=t.touches[0].clientY-this.touchStarts[0].client[1],n=this.touchStartTranslateX+s,r=this.touchStartTranslateY+a;this.setTranslateFromUserGesture(n,r)}this.update()}}handleTouchend(t){t.touches.length===0?this.touchStarts=null:(this.touchStarts=this.freezeTouches(t.touches),this.touchStartTranslateX=this.translateX,this.touchStartTranslateY=this.translateY)}calcProjectionTranslate(t,e,s,a){const n=this.canvasBounds.width*this.naturalScale,r=this.canvasBounds.height*this.naturalScale,i=s[0]*n*t,l=s[1]*r*t,o=T([i,l],[0,0],a??this.rotate),c=e[0]*this.wrapperInnerWidth,p=e[1]*this.wrapperInnerHeight,m=c-o[0],S=p-o[1];return[m,S]}applyTransform(t,e,s){const a=this.calcProjectionTranslate(t,e,s,0);this.scale=t,this.setTranslateFromUserGesture(a[0],a[1]),this.update()}composeRelPoint(t,e,s,a,n,r){s=s??this.scale,a=a??this.translateX,n=n??this.translateY,r=r??this.rotate;const i=[this.offset.left,this.offset.top],l=[this.offset.left+this.canvasBounds.width*(s*this.naturalScale)*t,this.offset.top+this.canvasBounds.height*(s*this.naturalScale)*e],o=T(l,i,r);return[o[0]+a,o[1]+n]}composePoint(t,e){const s=t/this.canvasBounds.width,a=e/this.canvasBounds.height;return this.composeRelPoint(s,a)}getAnchorOffset(t,e,s,a,n=[.5,.5]){const r=this.calcProjectionTranslate(t,n,n,0),i=[this.offset.left+r[0]+this.canvasBounds.width*(t*this.naturalScale)*n[0],this.offset.top+r[1]+this.canvasBounds.height*(t*this.naturalScale)*n[1]],l=this.composeRelPoint(n[0],n[1],t,e,s,a),o=l[0]-i[0],c=l[1]-i[1];return[o,c]}getCanvasCoordsRel(t,e){const s=[0,0],a=[t-this.translateX,e-this.translateY],n=T(a,s,-this.rotate),r=[n[0]/this.renderinScale,n[1]/this.renderinScale];return[r[0]/this.canvasBounds.width,r[1]/this.canvasBounds.height]}clientCoordsToWrapperCoords(t,e){return[t-this.wrapperInnerX,e-this.wrapperInnerY]}relativeWrapperCoordinatesFromClientCoords(t,e){const[s,a]=this.clientCoordsToWrapperCoords(t,e);return[s/this.wrapperInnerWidth,a/this.wrapperInnerHeight]}normalizeMatrixCoordinates(t,e){const s=this.clientCoordsToWrapperCoords(t,e);return this.getCanvasCoordsRel(s[0],s[1])}normalizeClientCoords(t,e){const[s,a]=this.normalizeMatrixCoordinates(t,e);return[s*this.canvasBounds.width,a*this.canvasBounds.height]}rotateCanvas(t,e,s){const a=t/this.canvasBounds.width,n=e/this.canvasBounds.height,r=this.composeRelPoint(a,n,this.scale,0,0,s),i=this.composeRelPoint(a,n);this.setTranslateFromUserGesture(i[0]-r[0],i[1]-r[1]),this.rotate=s,this.update()}get renderinScale(){return this.naturalScale*this.scale}get renderingTranslateX(){return this.offset.left+this.translateX}get renderingTranslateY(){return this.offset.top+this.translateY}get renderingRotate(){return this.rotate}clampTranslate(t,e=[.5,.5]){const s=this.canvasBounds.width*this.naturalScale*t.scale,a=this.canvasBounds.height*this.naturalScale*t.scale,n=s-this.wrapperInnerWidth,r=a-this.wrapperInnerHeight,i=n>0?-n:0,l=Math.min(0,Math.max(t.translateX,i)),o=r>0?-r:0,c=Math.min(0,Math.max(t.translateY,o)),p=-Math.min(0,n)*e[0],m=-Math.min(0,r)*e[1];return{translateX:l+p,translateY:c+m}}update(){this.canvasElement.style.transformOrigin="top left",this.canvasElement.style.transform=`translateX(${this.renderingTranslateX}px) translateY(${this.renderingTranslateY}px) scale(${this.renderinScale}) rotate(${this.renderingRotate}rad)`,this.dispatchEvent(new Event("update"))}destroy(){}}f.Zoompinch=F,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(p,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(p=typeof globalThis<"u"?globalThis:p||self,d(p.Zoompinch={}))})(this,(function(p){"use strict";var I=Object.defineProperty;var W=(p,d,w)=>d in p?I(p,d,{enumerable:!0,configurable:!0,writable:!0,value:w}):p[d]=w;var l=(p,d,w)=>W(p,typeof d!="symbol"?d+"":d,w);function d(u){return u*Math.PI/180}function w(u,m,t){return Math.min(Math.max(u,m),t)}function X(u,m,t){const[e,s]=u,[a,n]=m,r=Math.cos(t)*(e-a)-Math.sin(t)*(s-n)+a,i=Math.sin(t)*(e-a)+Math.cos(t)*(s-n)+n;return[r,i]}function M(u){if(u.ctrlKey){const{deltaY:t,deltaMode:e,ctrlKey:s}=u,a=Math.abs(t),n=a===120||a===100||a===3,r=t%1!==0,i=e===0;return s?a<50&&i||r:!n&&(r||i&&a<50)}else{var m=!1;return u.wheelDeltaY?u.wheelDeltaY===u.deltaY*-3&&(m=!0):u.deltaMode===0&&(m=!0),m}}class P extends EventTarget{constructor(t,e,s,a,n,r,i=.1,h=10,o=!1,c=!0){super();l(this,"wrapperBounds");l(this,"canvasBounds");l(this,"translateSpeed",1);l(this,"zoomSpeed",1);l(this,"translateSpeedAppleTrackpad",1);l(this,"zoomSpeedAppleTrackpad",1);l(this,"isGestureActive",!1);l(this,"gestureStartRotate",0);l(this,"dragStart",null);l(this,"dragStartFrozenX",null);l(this,"dragStartFrozenY",null);l(this,"touchStarts",null);l(this,"touchStartTranslateX",0);l(this,"touchStartTranslateY",0);this.element=t,this.offset=e,this.translateX=s,this.translateY=a,this.scale=n,this.rotate=r,this.minScale=i,this.maxScale=h,this.clampBounds=o,this.rotation=c;const f=new ResizeObserver(()=>{const{x:S,y:v,width:Y,height:B}=this.element.getBoundingClientRect();this.wrapperBounds={x:S,y:v,width:Y,height:B},this.update()}),g=new ResizeObserver(S=>{const{width:v,height:Y}=S[0].contentRect;(v!==this.canvasBounds.width||Y!==this.canvasBounds.height)&&(this.canvasBounds={...this.canvasBounds,width:v,height:Y},this.isGestureActive||this.update())});requestAnimationFrame(()=>{this.wrapperBounds=this.element.getBoundingClientRect(),this.canvasBounds=this.canvasElement.getBoundingClientRect(),this.update(),this.dispatchEvent(new Event("init"))}),g.observe(this.canvasElement),f.observe(this.element)}get canvasElement(){return this.element.querySelector(".canvas")}get wrapperInnerX(){return this.wrapperBounds.x+this.offset.left}get wrapperInnerY(){return this.wrapperBounds.y+this.offset.top}get wrapperInnerWidth(){return this.wrapperBounds.width-this.offset.left-this.offset.right}get wrapperInnerHeight(){return this.wrapperBounds.height-this.offset.top-this.offset.bottom}get wrapperInnerRatio(){return this.wrapperInnerWidth/this.wrapperInnerHeight}get canvasNaturalRatio(){return this.canvasBounds.width/this.canvasBounds.height}get naturalScale(){return this.canvasNaturalRatio>=this.wrapperInnerRatio?this.wrapperInnerWidth/this.canvasBounds.width:this.wrapperInnerHeight/this.canvasBounds.height}setTranslateFromUserGesture(t,e){if(this.clampBounds){const s=this.clampTranslate({translateX:t,translateY:e,scale:this.scale,rotate:this.rotate});this.translateX=s.translateX,this.translateY=s.translateY,this.rotate=0}else this.translateX=t,this.translateY=e}handleGesturestart(t){this.gestureStartRotate=this.rotate}handleGesturechange(t){const{clientX:e,clientY:s}=t,a=t.rotation;if(a===0||!this.rotation)return;const n=this.normalizeClientCoords(e,s);this.rotateCanvas(n[0],n[1],this.gestureStartRotate+d(a))}handleGestureend(t){}handleMousedown(t){t.preventDefault(),this.dragStart=[t.clientX,t.clientY],this.dragStartFrozenX=this.translateX,this.dragStartFrozenY=this.translateY}handleMouseup(t){t.preventDefault(),this.dragStart=null,this.dragStartFrozenX=null,this.dragStartFrozenY=null}handleMousemove(t){if(t.preventDefault(),this.dragStart&&this.dragStartFrozenX!==null&&this.dragStartFrozenY!==null){const e=t.clientX-this.dragStart[0],s=t.clientY-this.dragStart[1],a=this.dragStartFrozenX- -e,n=this.dragStartFrozenY- -s;this.setTranslateFromUserGesture(a,n),this.update()}}handleWheel(t){let{deltaX:e,deltaY:s,ctrlKey:a}=t;const n=M(t);n||(Math.abs(s)>=100&&(s=Math.sign(s)*(Math.abs(s)/120)),Math.abs(e)>=100&&(e=Math.sign(e)*(Math.abs(e)/120)));const r=this.scale;if(a){const i=n?.01*this.zoomSpeedAppleTrackpad:.1*this.zoomSpeed,h=1+-s*i;let o=r*h;if(o=w(o,this.minScale,this.maxScale),(o===this.minScale||o===this.maxScale)&&(o===this.minScale&&h<1||o===this.maxScale&&h>1)){t.preventDefault();return}const c=this.relativeWrapperCoordinatesFromClientCoords(t.clientX,t.clientY),[f,g]=this.calcProjectionTranslate(o,c,this.normalizeMatrixCoordinates(t.clientX,t.clientY));this.setTranslateFromUserGesture(f,g),this.scale=o}else{const i=n?1*this.translateSpeedAppleTrackpad:25*this.translateSpeed;this.setTranslateFromUserGesture(this.translateX-e*i,this.translateY-s*i)}this.update(),t.preventDefault()}freezeTouches(t){return Array.from(t).map(e=>{const s=this.clientCoordsToWrapperCoords(e.clientX,e.clientY);return{client:[e.clientX,e.clientY],canvasRel:this.getCanvasCoordsRel(s[0],s[1])}})}handleTouchstart(t){this.touchStarts=this.freezeTouches(t.touches),this.touchStartTranslateX=this.translateX,this.touchStartTranslateY=this.translateY,this.isGestureActive=!0,t.preventDefault()}handleTouchmove(t){t.preventDefault();const e=Array.from(t.touches).map(s=>this.clientCoordsToWrapperCoords(s.clientX,s.clientY));if(this.touchStarts){if(e.length>=2&&this.touchStarts.length>=2){const s=[this.touchStarts[0].canvasRel[0]*this.canvasBounds.width,this.touchStarts[0].canvasRel[1]*this.canvasBounds.height],a=[this.touchStarts[1].canvasRel[0]*this.canvasBounds.width,this.touchStarts[1].canvasRel[1]*this.canvasBounds.height],n=Math.sqrt(Math.pow(s[0]-a[0],2)+Math.pow(s[1]-a[1],2)),r=Math.sqrt(Math.pow(e[0][0]-e[1][0],2)+Math.pow(e[0][1]-e[1][1],2))/this.naturalScale,i=w(r/n,this.minScale,this.maxScale),h=[e[0][0]/this.wrapperInnerWidth,e[0][1]/this.wrapperInnerHeight],o=this.touchStarts[0].canvasRel,[c,f]=this.calcProjectionTranslate(i,h,o,0);if(this.rotation){let g=0,S=0,v=0;const Y=Math.atan2(a[1]-s[1],a[0]-s[0]);v=Math.atan2(e[1][1]-e[0][1],e[1][0]-e[0][0])-Y;const C=(F,x)=>[this.offset.left+this.canvasBounds.width*F*this.naturalScale*i+c,this.offset.top+this.canvasBounds.height*x*this.naturalScale*i+f],T=C(0,0),z=C(this.touchStarts[0].canvasRel[0],this.touchStarts[0].canvasRel[1]),R=X(T,z,v);g=R[0]-T[0],S=R[1]-T[1],this.scale=i,this.rotate=v,this.setTranslateFromUserGesture(c+g,f+S)}else this.scale=i,this.setTranslateFromUserGesture(c,f)}else{const s=t.touches[0].clientX-this.touchStarts[0].client[0],a=t.touches[0].clientY-this.touchStarts[0].client[1],n=this.touchStartTranslateX+s,r=this.touchStartTranslateY+a;this.setTranslateFromUserGesture(n,r)}this.update()}}handleTouchend(t){t.touches.length===0?this.touchStarts=null:(this.touchStarts=this.freezeTouches(t.touches),this.touchStartTranslateX=this.translateX,this.touchStartTranslateY=this.translateY),this.isGestureActive=!1}calcProjectionTranslate(t,e,s,a){const n=this.canvasBounds.width*this.naturalScale,r=this.canvasBounds.height*this.naturalScale,i=s[0]*n*t,h=s[1]*r*t,o=X([i,h],[0,0],a??this.rotate),c=e[0]*this.wrapperInnerWidth,f=e[1]*this.wrapperInnerHeight,g=c-o[0],S=f-o[1];return[g,S]}applyTransform(t,e,s){const a=this.calcProjectionTranslate(t,e,s,0);this.scale=t,this.setTranslateFromUserGesture(a[0],a[1]),this.update()}composeRelPoint(t,e,s,a,n,r){s=s??this.scale,a=a??this.translateX,n=n??this.translateY,r=r??this.rotate;const i=[this.offset.left,this.offset.top],h=[this.offset.left+this.canvasBounds.width*(s*this.naturalScale)*t,this.offset.top+this.canvasBounds.height*(s*this.naturalScale)*e],o=X(h,i,r);return[o[0]+a,o[1]+n]}composePoint(t,e){const s=t/this.canvasBounds.width,a=e/this.canvasBounds.height;return this.composeRelPoint(s,a)}getAnchorOffset(t,e,s,a,n=[.5,.5]){const r=this.calcProjectionTranslate(t,n,n,0),i=[this.offset.left+r[0]+this.canvasBounds.width*(t*this.naturalScale)*n[0],this.offset.top+r[1]+this.canvasBounds.height*(t*this.naturalScale)*n[1]],h=this.composeRelPoint(n[0],n[1],t,e,s,a),o=h[0]-i[0],c=h[1]-i[1];return[o,c]}getCanvasCoordsRel(t,e){const s=[0,0],a=[t-this.translateX,e-this.translateY],n=X(a,s,-this.rotate),r=[n[0]/this.renderinScale,n[1]/this.renderinScale];return[r[0]/this.canvasBounds.width,r[1]/this.canvasBounds.height]}clientCoordsToWrapperCoords(t,e){return[t-this.wrapperInnerX,e-this.wrapperInnerY]}relativeWrapperCoordinatesFromClientCoords(t,e){const[s,a]=this.clientCoordsToWrapperCoords(t,e);return[s/this.wrapperInnerWidth,a/this.wrapperInnerHeight]}normalizeMatrixCoordinates(t,e){const s=this.clientCoordsToWrapperCoords(t,e);return this.getCanvasCoordsRel(s[0],s[1])}normalizeClientCoords(t,e){const[s,a]=this.normalizeMatrixCoordinates(t,e);return[s*this.canvasBounds.width,a*this.canvasBounds.height]}rotateCanvas(t,e,s){const a=t/this.canvasBounds.width,n=e/this.canvasBounds.height,r=this.composeRelPoint(a,n,this.scale,0,0,s),i=this.composeRelPoint(a,n);this.setTranslateFromUserGesture(i[0]-r[0],i[1]-r[1]),this.rotate=s,this.update()}get renderinScale(){return this.naturalScale*this.scale}get renderingTranslateX(){return this.offset.left+this.translateX}get renderingTranslateY(){return this.offset.top+this.translateY}get renderingRotate(){return this.rotate}clampTranslate(t,e=[.5,.5]){const s=this.canvasBounds.width*this.naturalScale*t.scale,a=this.canvasBounds.height*this.naturalScale*t.scale,n=s-this.wrapperInnerWidth,r=a-this.wrapperInnerHeight,i=n>0?-n:0,h=Math.min(0,Math.max(t.translateX,i)),o=r>0?-r:0,c=Math.min(0,Math.max(t.translateY,o)),f=-Math.min(0,n)*e[0],g=-Math.min(0,r)*e[1];return{translateX:h+f,translateY:c+g}}update(){this.canvasElement.style.transformOrigin="top left",this.canvasElement.style.transform=`translateX(${this.renderingTranslateX}px) translateY(${this.renderingTranslateY}px) scale(${this.renderinScale}) rotate(${this.renderingRotate}rad)`,this.dispatchEvent(new Event("update"))}destroy(){}}p.Zoompinch=P,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/zoompinch.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export declare class Zoompinch extends EventTarget {
|
|
|
33
33
|
zoomSpeed: number;
|
|
34
34
|
translateSpeedAppleTrackpad: number;
|
|
35
35
|
zoomSpeedAppleTrackpad: number;
|
|
36
|
+
private isGestureActive;
|
|
36
37
|
constructor(element: HTMLElement, offset: Offset, translateX: number, translateY: number, scale: number, rotate: number, minScale?: number, maxScale?: number, clampBounds?: boolean, rotation?: boolean);
|
|
37
38
|
get canvasElement(): HTMLElement;
|
|
38
39
|
get wrapperInnerX(): number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zoompinch/core",
|
|
3
3
|
"description": "Pinch-and-zoom experience that's feels native and communicates the transform reactively and lets you project any layer on top of the transformed canvas",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.31",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/zoompinch-core.umd.js",
|