UNPKG

vevet

Version:

Vevet is a JavaScript library for creative development that simplifies crafting rich interactions like split text animations, carousels, marquees, preloading, and more.

446 lines 16.7 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SwipeCoords = void 0; var initVevet_1 = require("../../../global/initVevet"); var isFiniteNumber_1 = require("../../../internal/isFiniteNumber"); var unwrapAngle_1 = require("../../../internal/unwrapAngle"); var utils_1 = require("../../../utils"); var START_VEC3 = { x: 0, y: 0, angle: 0 }; var START_STATE = __assign(__assign({}, START_VEC3), { time: 0 }); var SwipeCoords = /** @class */ (function () { function SwipeCoords(ctx) { this.ctx = ctx; /** Event timestamp. */ this._timestamp = 0; /** Start position. */ this._start = __assign({}, START_STATE); /** Previous position. */ this._prev = __assign({}, START_STATE); /** Current position. */ this._current = __assign({}, START_STATE); /** Movement offset from start. */ this._diff = __assign({}, START_STATE); /** Movement offset from previous position. */ this._step = __assign({}, START_STATE); /** Total accumulated movement since swipe start. */ this._accum = __assign({}, START_VEC3); /** Movement with rubber and snap applied (movement space). */ this._movement = __assign({}, START_VEC3); /** Previous movement with rubber and snap applied (movement space). */ this._prevMovement = __assign({}, START_VEC3); /** Raw accumulated displacement (before rubber). */ this._rawMovement = __assign({}, START_VEC3); /** Raw atan2 angle and unwrapped cumulative angle. */ this._tempAngle = { raw: 0, unwrapped: 0 }; /** Active snap target per axis, if any. */ this._snap = {}; /** Cached normalized bounds (refreshed on swipe start). */ this._bounds = null; /** Current scale modifier. */ this._scale = 1; } Object.defineProperty(SwipeCoords.prototype, "timestamp", { get: function () { return this._timestamp; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "start", { get: function () { return this._start; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "prev", { get: function () { return this._prev; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "current", { get: function () { return this._current; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "diff", { get: function () { return this._diff; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "step", { get: function () { return this._step; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "accum", { get: function () { return this._accum; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "movement", { /** Displacement in movement space (rubber + snap). */ get: function () { return this._movement; }, set: function (value) { var newValue = __assign(__assign({}, this.movement), value); this._movement.x = newValue.x; this._movement.y = newValue.y; this._movement.angle = newValue.angle; this._rawMovement.x = newValue.x; this._rawMovement.y = newValue.y; this._rawMovement.angle = newValue.angle; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "prevMovement", { /** Previous displacement in movement space (rubber + snap). */ get: function () { return this._prevMovement; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "rawMovement", { /** Raw movement before rubber (same space as `bounds`). */ get: function () { return this._rawMovement; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "bounds", { /** Normalized movement limits (`[min, max]` per defined axis). */ get: function () { if (this._bounds) { return this._bounds; } return this.calculateBounds(); }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "overflow", { get: function () { return this.ctx.props.overflow ? Math.abs(this.ctx.props.overflow()) : 0; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "scale", { /** Current scale modifier */ get: function () { return this._scale; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "coords", { get: function () { var _a = this, timestamp = _a.timestamp, start = _a.start, prev = _a.prev, current = _a.current, diff = _a.diff, step = _a.step, accum = _a.accum, movement = _a.movement, prevMovement = _a.prevMovement, scale = _a.scale; return { timestamp: timestamp, start: start, prev: prev, current: current, diff: diff, step: step, accum: accum, movement: movement, prevMovement: prevMovement, scale: scale, }; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "snap", { /** Resolved snap target per axis during the current gesture. */ get: function () { return this._snap; }, enumerable: false, configurable: true }); Object.defineProperty(SwipeCoords.prototype, "exceeds", { /** * Overflow past `bounds` per axis in movement space. * Zero when inside limits; used for bounce-back. */ get: function () { var _a = this, movement = _a._rawMovement, bounds = _a.bounds; if (!bounds) { return null; } var xDiff = 0; var yDiff = 0; var aDiff = 0; if (bounds.x) { if (movement.x < bounds.x[0]) { xDiff = movement.x - bounds.x[0]; } else if (movement.x > bounds.x[1]) { xDiff = movement.x - bounds.x[1]; } } if (bounds.y) { if (movement.y < bounds.y[0]) { yDiff = movement.y - bounds.y[0]; } else if (movement.y > bounds.y[1]) { yDiff = movement.y - bounds.y[1]; } } if (bounds.angle) { if (movement.angle < bounds.angle[0]) { aDiff = movement.angle - bounds.angle[0]; } else if (movement.angle > bounds.angle[1]) { aDiff = movement.angle - bounds.angle[1]; } } return { x: xDiff, y: yDiff, angle: aDiff, }; }, enumerable: false, configurable: true }); /** Parses pointer coordinates relative to the container */ SwipeCoords.prototype.decode = function (event) { var vevet = (0, initVevet_1.initVevet)(); var _a = this.ctx, props = _a.props, container = _a.container; var clientX = 0; var clientY = 0; if ('touches' in event) { clientX = event.touches[0].clientX; clientY = event.touches[0].clientY; } else if ('type' in event) { clientX = event.clientX; clientY = event.clientY; } else { clientX = event.x; clientY = event.y; } var x = clientX; var y = clientY; var centerX = vevet.width / 2; var centerY = vevet.height / 2; if (props.relative) { var bounding = container.getBoundingClientRect(); x = clientX - bounding.left; y = clientY - bounding.top; centerX = bounding.left + bounding.width / 2; centerY = bounding.top + bounding.height / 2; } var angleRad = Math.atan2(clientY - centerY, clientX - centerX); var angle = (angleRad * 180) / Math.PI; return { x: x, y: y, angle: angle, time: performance.now(), }; }; /** Apply scale and optionally zoom toward an origin in movement space. */ SwipeCoords.prototype.applyScale = function (value, originProp) { if (this._scale === value) { return; } if (originProp) { var origin_1 = this.decode(originProp); var ratio = value / this._scale; this.movement = { x: origin_1.x - (origin_1.x - this._movement.x) * ratio, y: origin_1.y - (origin_1.y - this._movement.y) * ratio, }; } this._scale = value; }; /** Set start coordinates */ SwipeCoords.prototype.setStart = function (state) { this._tempAngle = { raw: state.angle, unwrapped: state.angle }; this._timestamp = performance.now(); this._start = __assign({}, state); this._prev = __assign({}, state); this._current = __assign({}, state); this._diff = __assign(__assign({}, START_VEC3), { time: 0 }); this._step = __assign(__assign({}, START_VEC3), { time: 0 }); this._accum = __assign({}, START_VEC3); }; /** Sync temp angle */ SwipeCoords.prototype.syncTempAngle = function () { this._tempAngle.raw = this._current.angle; this._tempAngle.unwrapped = this._current.angle; }; /** Update coordinates */ SwipeCoords.prototype.update = function (_a, applyRatio) { var x = _a.x, y = _a.y, angle = _a.angle, time = _a.time; if (applyRatio === void 0) { applyRatio = true; } // Vars var _b = this, start = _b.start, ctx = _b.ctx; var stepRatio = applyRatio ? ctx.props.ratio : 1; // Update bounds if ((ctx.hasInertia() && ctx.recalculateBoundsOnInertia()) || !ctx.hasInertia()) { this.calculateBounds(); } // Save this._timestamp = performance.now(); this._prev = __assign({}, this.current); this._current = { x: x, y: y, angle: angle, time: time }; var _c = this, current = _c._current, prev = _c._prev, overflow = _c.overflow; // Update angle this._updateTempAngle(angle); current.angle = this._tempAngle.unwrapped; // Update coords this._step = { x: current.x - prev.x, y: current.y - prev.y, angle: current.angle - prev.angle, time: current.time - prev.time, }; this._diff = { x: current.x - start.x, y: current.y - start.y, angle: this._diff.angle + this._step.angle, time: current.time - start.time, }; this._accum = { x: this._accum.x + Math.abs(this._step.x), y: this._accum.y + Math.abs(this._step.y), angle: this._accum.angle + Math.abs(this._step.angle), }; this._rawMovement = { x: this._rawMovement.x + this._step.x * stepRatio, y: this._rawMovement.y + this._step.y * stepRatio, angle: this._rawMovement.angle + this._step.angle * stepRatio, }; this._prevMovement.x = this._movement.x; this._prevMovement.y = this._movement.y; this._prevMovement.angle = this._movement.angle; this._movement.x = this._applyRubber('x', overflow); this._movement.y = this._applyRubber('y', overflow); this._movement.angle = this._applyRubber('angle', overflow); this._snapMovementAxis('x'); this._snapMovementAxis('y'); this._snapMovementAxis('angle'); }; /** Snap movement axis */ SwipeCoords.prototype._snapMovementAxis = function (axis) { var _a; var _b = this.ctx, props = _b.props, hasInertia = _b.hasInertia; var snap = (_a = props.snap) === null || _a === void 0 ? void 0 : _a.call(props); if (!snap) { this._snap[axis] = undefined; return; } var snaps = snap[axis]; if (!(snaps === null || snaps === void 0 ? void 0 : snaps.length)) { this._snap[axis] = undefined; return; } var value = this._movement[axis]; var target = (0, utils_1.closest)(value, snaps); var radius = props.snapRadius; if ((0, isFiniteNumber_1.isFiniteNumber)(radius) && Math.abs(target - value) > Math.abs(radius)) { this._snap[axis] = undefined; return; } this._snap[axis] = target; if (!hasInertia()) { this._movement[axis] = target; } }; /** Calculate bounds */ SwipeCoords.prototype.calculateBounds = function () { var props = this.ctx.props; if (!props.bounds) { this._bounds = null; return; } var bounds = props.bounds(this.coords); var d = [-Infinity, Infinity]; var x = (bounds === null || bounds === void 0 ? void 0 : bounds.x) ? [Math.min.apply(Math, bounds.x), Math.max.apply(Math, bounds.x)] : __spreadArray([], d, true); var y = (bounds === null || bounds === void 0 ? void 0 : bounds.y) ? [Math.min.apply(Math, bounds.y), Math.max.apply(Math, bounds.y)] : __spreadArray([], d, true); var a = (bounds === null || bounds === void 0 ? void 0 : bounds.angle) ? [Math.min.apply(Math, bounds.angle), Math.max.apply(Math, bounds.angle)] : __spreadArray([], d, true); this._bounds = { x: x, y: y, angle: a }; return this._bounds; }; /** Unwrap raw atan2 angle and accumulate into _angle */ SwipeCoords.prototype._updateTempAngle = function (rawAngle) { this._tempAngle.unwrapped += (0, unwrapAngle_1.unwrapAngleDelta)(rawAngle, this._tempAngle.raw); this._tempAngle.raw = rawAngle; }; /** Apply rubber-band past movement bounds. */ SwipeCoords.prototype._applyRubber = function (axis, overflow) { var _a; var temp = this._rawMovement[axis]; var bounds = (_a = this.bounds) === null || _a === void 0 ? void 0 : _a[axis]; if (!bounds) { return temp; } var min = bounds[0], max = bounds[1]; if (temp >= min && temp <= max) { return temp; } if (temp < min) { return min - this._rubberDistance(min - temp, overflow); } return max + this._rubberDistance(temp - max, overflow); }; /** * Overscroll → rubber displacement */ SwipeCoords.prototype._rubberDistance = function (overscroll, limit) { if (overscroll <= 0 || limit <= 0) { return 0; } return (limit * overscroll) / (limit + overscroll); }; return SwipeCoords; }()); exports.SwipeCoords = SwipeCoords; //# sourceMappingURL=index.js.map