@quillmark/svelte 0.26.0 → 0.26.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.
- package/dist/preview/viewport.js +52 -26
- package/package.json +1 -1
package/dist/preview/viewport.js
CHANGED
|
@@ -13,6 +13,9 @@ const WHEEL_RATE = [0.0025, 0.08, 0.25];
|
|
|
13
13
|
* rate that inverts the pinch's encoding. */
|
|
14
14
|
const PINCH_DELTA = 50;
|
|
15
15
|
const PINCH_RATE = 0.01;
|
|
16
|
+
/** How far, as a log of the spread's ratio, two fingers part or close before a touch
|
|
17
|
+
* pinch zooms rather than only pans. */
|
|
18
|
+
const PINCH_SLOP = 0.04;
|
|
16
19
|
const px = (value) => parseFloat(value) || 0;
|
|
17
20
|
export function createViewport(container, slots, setScale, resetLabel) {
|
|
18
21
|
let zoom;
|
|
@@ -154,14 +157,13 @@ export function createViewport(container, slots, setScale, resetLabel) {
|
|
|
154
157
|
const factor = Math.exp(-e.deltaY * (pinched ? PINCH_RATE : WHEEL_RATE[e.deltaMode]));
|
|
155
158
|
glideTo((g) => g.raw * factor, e.clientX, e.clientY);
|
|
156
159
|
}
|
|
157
|
-
// The keys
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
// a host's own handler took is left to it.
|
|
160
|
+
// The keys are the focused pane's alone: elsewhere they are the browser's own zoom,
|
|
161
|
+
// the pointer over the pane notwithstanding. A key a host's own handler took is left
|
|
162
|
+
// to it.
|
|
161
163
|
function onKeyDown(e) {
|
|
162
164
|
if (!(e.ctrlKey || e.metaKey) || e.altKey || e.defaultPrevented || e.isComposing)
|
|
163
165
|
return;
|
|
164
|
-
if (!
|
|
166
|
+
if (!container.contains(document.activeElement))
|
|
165
167
|
return;
|
|
166
168
|
const dir = e.key === '=' || e.key === '+' ? 1 : e.key === '-' || e.key === '_' ? -1 : 0;
|
|
167
169
|
if ((!dir && e.key !== '0') || !bounds())
|
|
@@ -169,30 +171,54 @@ export function createViewport(container, slots, setScale, resetLabel) {
|
|
|
169
171
|
e.preventDefault();
|
|
170
172
|
step((b) => (dir ? stepZoom(b.current, dir, b.floor) : undefined));
|
|
171
173
|
}
|
|
172
|
-
// A two-finger pinch on a touch screen. The browser's own page zoom is held off by the
|
|
173
|
-
// desk's `touch-action` and by cancelling the move, which also stops the pan a second
|
|
174
|
-
// finger would otherwise start.
|
|
175
174
|
let pinch;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
// The fingers on this pane, not one resting on the editor beside it.
|
|
176
|
+
const fingers = (e) => [...e.touches].filter((t) => t.target instanceof Node && container.contains(t.target));
|
|
177
|
+
const spread = ([a, b]) => Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY);
|
|
178
|
+
const midpoint = ([a, b]) => ({
|
|
179
|
+
x: (a.clientX + b.clientX) / 2,
|
|
180
|
+
y: (a.clientY + b.clientY) / 2
|
|
181
|
+
});
|
|
182
|
+
function grip(at) {
|
|
183
|
+
const page = pageAt(at.y);
|
|
184
|
+
const r = page?.getBoundingClientRect();
|
|
185
|
+
if (!page || !r?.width || !r.height)
|
|
186
|
+
return undefined;
|
|
187
|
+
return { page, fx: (at.x - r.left) / r.width, fy: (at.y - r.top) / r.height };
|
|
188
|
+
}
|
|
189
|
+
// A finger landing or lifting starts the pinch over with the two that remain.
|
|
190
|
+
function onTouches(e) {
|
|
191
|
+
pinch = undefined;
|
|
192
|
+
const t = fingers(e);
|
|
180
193
|
const b = bounds();
|
|
181
|
-
|
|
182
|
-
|
|
194
|
+
const held = t.length === 2 && b ? grip(midpoint(t)) : undefined;
|
|
195
|
+
if (held)
|
|
196
|
+
pinch = { spread: spread(t), raw: from(b).raw, zooming: false, ...held };
|
|
183
197
|
}
|
|
184
198
|
function onTouchMove(e) {
|
|
185
|
-
|
|
199
|
+
const t = fingers(e);
|
|
200
|
+
if (!pinch || t.length !== 2)
|
|
186
201
|
return;
|
|
187
202
|
e.preventDefault();
|
|
188
|
-
const
|
|
189
|
-
const ratio = spread(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
pinch =
|
|
203
|
+
const mid = midpoint(t);
|
|
204
|
+
const ratio = spread(t) / pinch.spread;
|
|
205
|
+
if (pinch.zooming) {
|
|
206
|
+
const start = pinch.raw;
|
|
207
|
+
glideTo(() => start * ratio, mid.x, mid.y);
|
|
208
|
+
}
|
|
209
|
+
else if (Math.abs(Math.log(ratio)) >= PINCH_SLOP) {
|
|
210
|
+
pinch.zooming = true;
|
|
211
|
+
pinch.spread = spread(t);
|
|
212
|
+
}
|
|
213
|
+
// A move the browser is already scrolling cannot be cancelled: its pan stands, and
|
|
214
|
+
// the pinch holds whatever is under the fingers now.
|
|
215
|
+
if (!e.cancelable) {
|
|
216
|
+
Object.assign(pinch, grip(mid));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const r = pinch.page.getBoundingClientRect();
|
|
220
|
+
container.scrollLeft += r.left + pinch.fx * r.width - mid.x;
|
|
221
|
+
container.scrollTop += r.top + pinch.fy * r.height - mid.y;
|
|
196
222
|
}
|
|
197
223
|
// Safari's trackpad pinch. iOS sends these beside the touches, which are the ones read
|
|
198
224
|
// there; either way the page zoom is cancelled.
|
|
@@ -231,10 +257,10 @@ export function createViewport(container, slots, setScale, resetLabel) {
|
|
|
231
257
|
const listeners = [
|
|
232
258
|
[container, 'wheel', onWheel, { passive: false }],
|
|
233
259
|
[window, 'keydown', onKeyDown],
|
|
234
|
-
[container, 'touchstart',
|
|
260
|
+
[container, 'touchstart', onTouches, { passive: true }],
|
|
235
261
|
[container, 'touchmove', onTouchMove, { passive: false }],
|
|
236
|
-
[container, 'touchend',
|
|
237
|
-
[container, 'touchcancel',
|
|
262
|
+
[container, 'touchend', onTouches],
|
|
263
|
+
[container, 'touchcancel', onTouches],
|
|
238
264
|
[container, 'gesturestart', onGestureStart],
|
|
239
265
|
[container, 'gesturechange', onGestureChange],
|
|
240
266
|
[container, 'gestureend', onGestureEnd],
|