vevet 5.0.10 → 5.0.11
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/README.md +2 -0
- package/lib/cdn/vevet.iife.min.js +5 -5
- package/lib/cjs/components/Snap/Swipe/index.js +47 -6
- package/lib/cjs/components/Snap/Swipe/index.js.map +1 -1
- package/lib/cjs/components/Snap/Wheel/index.js +33 -16
- package/lib/cjs/components/Snap/Wheel/index.js.map +1 -1
- package/lib/cjs/components/Snap/index.js +31 -9
- package/lib/cjs/components/Snap/index.js.map +1 -1
- package/lib/cjs/components/Swipe/index.js +89 -46
- package/lib/cjs/components/Swipe/index.js.map +1 -1
- package/lib/cjs/manifest.json +1 -1
- package/lib/cjs/utils/math/clamp.js +3 -1
- package/lib/cjs/utils/math/clamp.js.map +1 -1
- package/lib/esm/components/Snap/Swipe/index.js +31 -6
- package/lib/esm/components/Snap/Swipe/index.js.map +1 -1
- package/lib/esm/components/Snap/Wheel/index.js +33 -16
- package/lib/esm/components/Snap/Wheel/index.js.map +1 -1
- package/lib/esm/components/Snap/index.js +29 -7
- package/lib/esm/components/Snap/index.js.map +1 -1
- package/lib/esm/components/Swipe/index.js +85 -42
- package/lib/esm/components/Swipe/index.js.map +1 -1
- package/lib/esm/manifest.json +1 -1
- package/lib/esm/utils/math/clamp.js +3 -1
- package/lib/esm/utils/math/clamp.js.map +1 -1
- package/lib/types/components/Snap/Swipe/index.d.ts +2 -0
- package/lib/types/components/Snap/Swipe/index.d.ts.map +1 -1
- package/lib/types/components/Snap/Swipe/types.d.ts +10 -0
- package/lib/types/components/Snap/Swipe/types.d.ts.map +1 -1
- package/lib/types/components/Snap/Wheel/index.d.ts +1 -1
- package/lib/types/components/Snap/Wheel/index.d.ts.map +1 -1
- package/lib/types/components/Snap/Wheel/types.d.ts +8 -2
- package/lib/types/components/Snap/Wheel/types.d.ts.map +1 -1
- package/lib/types/components/Snap/index.d.ts +1 -1
- package/lib/types/components/Snap/index.d.ts.map +1 -1
- package/lib/types/components/Swipe/index.d.ts +2 -6
- package/lib/types/components/Swipe/index.d.ts.map +1 -1
- package/lib/types/components/Swipe/types.d.ts +7 -2
- package/lib/types/components/Swipe/types.d.ts.map +1 -1
- package/lib/types/utils/math/clamp.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Snap/Swipe/index.ts +49 -8
- package/src/components/Snap/Swipe/types.ts +12 -0
- package/src/components/Snap/Wheel/index.ts +37 -18
- package/src/components/Snap/Wheel/types.ts +9 -2
- package/src/components/Snap/index.ts +31 -5
- package/src/components/Swipe/index.ts +106 -56
- package/src/components/Swipe/types.ts +8 -2
- package/src/manifest.json +1 -1
- package/src/utils/math/clamp.ts +4 -1
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
lerp,
|
|
21
21
|
toPixels,
|
|
22
22
|
closest,
|
|
23
|
+
clamp,
|
|
23
24
|
} from '@/utils';
|
|
24
25
|
import { SnapSlide } from './Slide';
|
|
25
26
|
import { SnapWheel } from './Wheel';
|
|
@@ -85,11 +86,14 @@ export class Snap<
|
|
|
85
86
|
swipeLerp: initVevet().mobile ? 1 : 0.6,
|
|
86
87
|
swipeThreshold: 5,
|
|
87
88
|
swipeMinTime: 0,
|
|
89
|
+
swipeInertiaDuration: (distance) => clamp(distance, 500, 2000),
|
|
90
|
+
swipeInertiaRatio: 0.3,
|
|
88
91
|
wheel: false,
|
|
89
92
|
wheelSpeed: 1,
|
|
90
93
|
wheelAxis: 'auto',
|
|
91
94
|
followWheel: true,
|
|
92
95
|
wheelThrottle: 'auto',
|
|
96
|
+
wheelNoFollowThreshold: 100,
|
|
93
97
|
stickOnWheelEnd: true,
|
|
94
98
|
slideSize: 'auto',
|
|
95
99
|
} as TRequiredProps<MutableProps>;
|
|
@@ -331,7 +335,9 @@ export class Snap<
|
|
|
331
335
|
|
|
332
336
|
// Get lerp factor
|
|
333
337
|
const lerpFactor =
|
|
334
|
-
swipe.isSwiping
|
|
338
|
+
(swipe.isSwiping || swipe.hasInertia) && props.swipeLerp
|
|
339
|
+
? props.swipeLerp
|
|
340
|
+
: props.lerp;
|
|
335
341
|
|
|
336
342
|
// Interpolate track value
|
|
337
343
|
track.lerp(this._raf.lerpFactor(lerpFactor));
|
|
@@ -500,7 +506,7 @@ export class Snap<
|
|
|
500
506
|
}
|
|
501
507
|
|
|
502
508
|
/** Go to a definite coordinate */
|
|
503
|
-
public toCoord(coordinate: number,
|
|
509
|
+
public toCoord(coordinate: number, durationProp = this.props.duration) {
|
|
504
510
|
if (this.isEmpty) {
|
|
505
511
|
return false;
|
|
506
512
|
}
|
|
@@ -513,8 +519,14 @@ export class Snap<
|
|
|
513
519
|
const end = coordinate;
|
|
514
520
|
const diff = Math.abs(end - start);
|
|
515
521
|
|
|
522
|
+
let duration =
|
|
523
|
+
typeof durationProp === 'number' ? durationProp : durationProp(diff);
|
|
524
|
+
if (diff === 0) {
|
|
525
|
+
duration = 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
516
528
|
const tm = new Timeline({
|
|
517
|
-
duration
|
|
529
|
+
duration,
|
|
518
530
|
easing: props.easing,
|
|
519
531
|
});
|
|
520
532
|
|
|
@@ -573,16 +585,30 @@ export class Snap<
|
|
|
573
585
|
|
|
574
586
|
this._targetIndex = index;
|
|
575
587
|
const slideMagnets = slides[index].magnets;
|
|
588
|
+
let targetStaticMagnet = slideMagnets[0];
|
|
589
|
+
|
|
590
|
+
if (props.centered) {
|
|
591
|
+
if (direction === 'prev') {
|
|
592
|
+
targetStaticMagnet = slideMagnets[2] ?? slideMagnets[0];
|
|
593
|
+
} else if (direction === 'next') {
|
|
594
|
+
targetStaticMagnet = slideMagnets[1] ?? slideMagnets[0];
|
|
595
|
+
}
|
|
596
|
+
} else {
|
|
597
|
+
targetStaticMagnet =
|
|
598
|
+
direction === 'prev'
|
|
599
|
+
? slideMagnets[slideMagnets.length - 1]
|
|
600
|
+
: targetStaticMagnet;
|
|
601
|
+
}
|
|
576
602
|
|
|
577
603
|
// Use static magnet when not looping
|
|
578
604
|
|
|
579
605
|
if (!props.loop) {
|
|
580
|
-
return this.toCoord(
|
|
606
|
+
return this.toCoord(targetStaticMagnet, duration);
|
|
581
607
|
}
|
|
582
608
|
|
|
583
609
|
// Or calculate closest magnet
|
|
584
610
|
|
|
585
|
-
const targetMagnet =
|
|
611
|
+
const targetMagnet = targetStaticMagnet + loopCount * max;
|
|
586
612
|
const targetMagnetMin = targetMagnet - max;
|
|
587
613
|
const targetMagnetMax = targetMagnet + max;
|
|
588
614
|
const allMagnets = [targetMagnetMin, targetMagnet, targetMagnetMax];
|
|
@@ -17,6 +17,9 @@ import { cursorStyles } from './styles';
|
|
|
17
17
|
|
|
18
18
|
export * from './types';
|
|
19
19
|
|
|
20
|
+
const VELOCITIES_COUNT = 4;
|
|
21
|
+
const MIN_VELOCITY_THRESHOLD = 50;
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* Manages swipe interactions:
|
|
22
25
|
* - Tracks movement and detects direction
|
|
@@ -67,9 +70,10 @@ export class Swipe<
|
|
|
67
70
|
preventTouchMove: true,
|
|
68
71
|
requireCtrlKey: false,
|
|
69
72
|
inertia: false,
|
|
70
|
-
inertiaDuration: (distance) => clamp(distance,
|
|
73
|
+
inertiaDuration: (distance) => clamp(distance, 500, 2000),
|
|
71
74
|
inertiaEasing: EaseOutCubic,
|
|
72
|
-
|
|
75
|
+
velocityModifier: false,
|
|
76
|
+
inertiaRatio: 1,
|
|
73
77
|
} as TRequiredProps<MutableProps>;
|
|
74
78
|
}
|
|
75
79
|
|
|
@@ -439,7 +443,12 @@ export class Swipe<
|
|
|
439
443
|
};
|
|
440
444
|
|
|
441
445
|
// update velocity
|
|
442
|
-
this.
|
|
446
|
+
if (!this.hasInertia) {
|
|
447
|
+
this._velocities.push({ ...coords.current, timestamp: coords.timestamp });
|
|
448
|
+
if (this._velocities.length > VELOCITIES_COUNT) {
|
|
449
|
+
this._velocities.shift();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
443
452
|
|
|
444
453
|
// trigger callbacks
|
|
445
454
|
this.callbacks.emit('move', this._coords);
|
|
@@ -459,11 +468,6 @@ export class Swipe<
|
|
|
459
468
|
// reset
|
|
460
469
|
this._reset();
|
|
461
470
|
|
|
462
|
-
// end with inertia
|
|
463
|
-
if (this.props.inertia) {
|
|
464
|
-
this._endWithInertia();
|
|
465
|
-
}
|
|
466
|
-
|
|
467
471
|
// reset cursor
|
|
468
472
|
this._cursorStyles.remove();
|
|
469
473
|
|
|
@@ -493,6 +497,17 @@ export class Swipe<
|
|
|
493
497
|
|
|
494
498
|
// end callback
|
|
495
499
|
this.callbacks.emit('end', this._coords);
|
|
500
|
+
|
|
501
|
+
// modifiy last velocity time
|
|
502
|
+
if (this._velocities.length > 0) {
|
|
503
|
+
this._velocities[this._velocities.length - 1].timestamp =
|
|
504
|
+
performance.now();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// end with inertia
|
|
508
|
+
if (this.props.inertia) {
|
|
509
|
+
this._endWithInertia();
|
|
510
|
+
}
|
|
496
511
|
}
|
|
497
512
|
|
|
498
513
|
/** Reset swipe states */
|
|
@@ -501,21 +516,90 @@ export class Swipe<
|
|
|
501
516
|
this._isSwiping = false;
|
|
502
517
|
}
|
|
503
518
|
|
|
519
|
+
/** Returns current velocity */
|
|
520
|
+
protected get velocity(): ISwipeMatrix {
|
|
521
|
+
const samples = this._velocities;
|
|
522
|
+
|
|
523
|
+
if (samples.length < 2) {
|
|
524
|
+
return { x: 0, y: 0, angle: 0 };
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
let totalWeight = 0;
|
|
528
|
+
let wvx = 0;
|
|
529
|
+
let wvy = 0;
|
|
530
|
+
let wva = 0;
|
|
531
|
+
|
|
532
|
+
for (let i = 1; i < samples.length; i += 1) {
|
|
533
|
+
const current = samples[i];
|
|
534
|
+
const previous = samples[i - 1];
|
|
535
|
+
|
|
536
|
+
const deltaX = current.x - previous.x;
|
|
537
|
+
const deltaY = current.y - previous.y;
|
|
538
|
+
|
|
539
|
+
let angleDiff = current.angle - previous.angle;
|
|
540
|
+
if (angleDiff > 180) angleDiff -= 360;
|
|
541
|
+
if (angleDiff < -180) angleDiff += 360;
|
|
542
|
+
|
|
543
|
+
const deltatTime = current.timestamp - previous.timestamp;
|
|
544
|
+
|
|
545
|
+
const sx = (deltaX / deltatTime) * 1000;
|
|
546
|
+
const sy = (deltaY / deltatTime) * 1000;
|
|
547
|
+
const sa = (angleDiff / deltatTime) * 1000;
|
|
548
|
+
|
|
549
|
+
const weight = 1 / Math.exp(-deltatTime * 0.1);
|
|
550
|
+
wvx += sx * weight;
|
|
551
|
+
wvy += sy * weight;
|
|
552
|
+
wva += sa * weight;
|
|
553
|
+
totalWeight += weight;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (totalWeight > 0) {
|
|
557
|
+
return {
|
|
558
|
+
x: wvx / totalWeight,
|
|
559
|
+
y: wvy / totalWeight,
|
|
560
|
+
angle: wva / totalWeight,
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return { x: 0, y: 0, angle: 0 };
|
|
565
|
+
}
|
|
566
|
+
|
|
504
567
|
/** Apply inertia-based movement */
|
|
505
568
|
protected _endWithInertia() {
|
|
506
|
-
const {
|
|
507
|
-
|
|
569
|
+
const { inertiaDuration, inertiaEasing, velocityModifier, inertiaRatio } =
|
|
570
|
+
this.props;
|
|
571
|
+
|
|
572
|
+
const sourceVelocity = {
|
|
573
|
+
x: this.velocity.x * inertiaRatio,
|
|
574
|
+
y: this.velocity.y * inertiaRatio,
|
|
575
|
+
angle: this.velocity.angle * inertiaRatio,
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
const velocity = velocityModifier
|
|
579
|
+
? velocityModifier(sourceVelocity)
|
|
580
|
+
: sourceVelocity;
|
|
581
|
+
|
|
582
|
+
const { x: velocityX, y: velocityY, angle: velocityA } = velocity;
|
|
583
|
+
const distance = Math.sqrt(velocityX ** 2 + velocityY ** 2);
|
|
584
|
+
|
|
585
|
+
// Check if we have sufficient velocity
|
|
586
|
+
if (distance < MIN_VELOCITY_THRESHOLD) {
|
|
508
587
|
return;
|
|
509
588
|
}
|
|
510
589
|
|
|
511
|
-
|
|
512
|
-
const { x: xDistance, y: yDistance, angle: angleDistance } = velocity;
|
|
513
|
-
|
|
514
|
-
const distance = Math.max(Math.abs(xDistance), Math.abs(yDistance));
|
|
590
|
+
// Calculate animation duration
|
|
515
591
|
const duration = inertiaDuration(distance);
|
|
516
592
|
|
|
593
|
+
// Check if the animation duration is positive
|
|
594
|
+
if (duration <= 0) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Calculate the start and add matrices
|
|
517
599
|
const startMatrix = { ...this.coords.current };
|
|
600
|
+
const addMatrix = { x: 0, y: 0, angle: 0 };
|
|
518
601
|
|
|
602
|
+
// Start the inertia animation
|
|
519
603
|
this._inertia = new Timeline({ duration, easing: inertiaEasing });
|
|
520
604
|
|
|
521
605
|
this._inertia.on('start', () => {
|
|
@@ -523,10 +607,15 @@ export class Swipe<
|
|
|
523
607
|
});
|
|
524
608
|
|
|
525
609
|
this._inertia.on('update', ({ eased }) => {
|
|
610
|
+
addMatrix.x = velocityX * eased;
|
|
611
|
+
addMatrix.y = velocityY * eased;
|
|
612
|
+
addMatrix.angle = velocityA * eased;
|
|
613
|
+
|
|
614
|
+
// Apply the calculated position
|
|
526
615
|
this._move({
|
|
527
|
-
x: startMatrix.x +
|
|
528
|
-
y: startMatrix.y +
|
|
529
|
-
angle: startMatrix.angle +
|
|
616
|
+
x: startMatrix.x + addMatrix.x,
|
|
617
|
+
y: startMatrix.y + addMatrix.y,
|
|
618
|
+
angle: startMatrix.angle + addMatrix.angle,
|
|
530
619
|
});
|
|
531
620
|
|
|
532
621
|
this.callbacks.emit('inertia', undefined);
|
|
@@ -549,45 +638,6 @@ export class Swipe<
|
|
|
549
638
|
this._inertia = undefined;
|
|
550
639
|
}
|
|
551
640
|
|
|
552
|
-
/** Returns current velocity */
|
|
553
|
-
protected get velocity() {
|
|
554
|
-
if (this._velocities.length < 2) {
|
|
555
|
-
return undefined;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const ratio = 1000 * this.props.inertiaRatio;
|
|
559
|
-
const minimumVelocity = 0.02;
|
|
560
|
-
|
|
561
|
-
const current = this._velocities.pop()!;
|
|
562
|
-
const last = this._velocities.pop()!;
|
|
563
|
-
|
|
564
|
-
const now = performance.now();
|
|
565
|
-
const timeDiff = current.timestamp - last.timestamp;
|
|
566
|
-
|
|
567
|
-
const velocityX = (current.x - last.x) / timeDiff / 2;
|
|
568
|
-
const velocityY = (current.y - last.y) / timeDiff / 2;
|
|
569
|
-
const velocityAngle = (current.angle - last.angle) / timeDiff / 2;
|
|
570
|
-
|
|
571
|
-
const hasXVelocity = Math.abs(velocityX) > minimumVelocity;
|
|
572
|
-
const hasYVelocity = Math.abs(velocityY) > minimumVelocity;
|
|
573
|
-
const hasAngleVelocity = Math.abs(velocityAngle) > minimumVelocity;
|
|
574
|
-
|
|
575
|
-
const hasVelocityByTime = timeDiff < 150 && now - current.timestamp < 300;
|
|
576
|
-
|
|
577
|
-
const hasVelocity =
|
|
578
|
-
(hasXVelocity || hasYVelocity || hasAngleVelocity) && hasVelocityByTime;
|
|
579
|
-
|
|
580
|
-
if (!hasVelocity) {
|
|
581
|
-
return undefined;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
return {
|
|
585
|
-
x: hasXVelocity ? velocityX * ratio : 0,
|
|
586
|
-
y: hasYVelocity ? velocityY * ratio : 0,
|
|
587
|
-
angle: hasAngleVelocity ? velocityAngle * ratio : 0,
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
|
-
|
|
591
641
|
/** Start coordinate */
|
|
592
642
|
get start() {
|
|
593
643
|
return this._coords.start;
|
|
@@ -117,7 +117,7 @@ export interface ISwipeMutableProps extends IModuleMutableProps {
|
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
119
|
* Inertia duration.
|
|
120
|
-
* @default `(distance) => clamp(distance,
|
|
120
|
+
* @default `(distance) => clamp(distance, 500, 2000)`
|
|
121
121
|
*/
|
|
122
122
|
inertiaDuration?: (distance: number) => number;
|
|
123
123
|
|
|
@@ -127,9 +127,15 @@ export interface ISwipeMutableProps extends IModuleMutableProps {
|
|
|
127
127
|
*/
|
|
128
128
|
inertiaEasing?: TEasingType;
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Final velocity modifier.
|
|
132
|
+
* @default false
|
|
133
|
+
*/
|
|
134
|
+
velocityModifier?: false | ((velocity: ISwipeMatrix) => ISwipeMatrix);
|
|
135
|
+
|
|
130
136
|
/**
|
|
131
137
|
* Inertia strength.
|
|
132
|
-
* @default
|
|
138
|
+
* @default 1
|
|
133
139
|
*/
|
|
134
140
|
inertiaRatio?: number;
|
|
135
141
|
}
|
package/src/manifest.json
CHANGED
package/src/utils/math/clamp.ts
CHANGED
|
@@ -16,5 +16,8 @@
|
|
|
16
16
|
* clamp(0.5, 0, 1); // 0.5
|
|
17
17
|
*/
|
|
18
18
|
export function clamp(value: number, min = 0, max = 1) {
|
|
19
|
-
|
|
19
|
+
const realMin = Math.min(min, max);
|
|
20
|
+
const realMax = Math.max(min, max);
|
|
21
|
+
|
|
22
|
+
return Math.max(realMin, Math.min(value, realMax));
|
|
20
23
|
}
|