/
githubmirror
/
anime
Обзор
Документация
Войти
/
githubmirror
/
anime
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
4.0.0
src/stagger.js
106 строк
3 KB
Julian Garnier
v4.0.0
03 апр 2025, 16:31
03 апр 2025, 16:31
66cfea7
Код
Авторство
О чём код?
/// <reference path='./types.js' /> import { emptyString, unitsExecRgx, } from './consts.js'; import { isArr, isUnd, isNum, parseNumber, round, abs, floor, sqrt, max, } from './helpers.js'; import { parseEasings, } from './eases.js'; import { Timeline, parseTimelinePosition, } from './timeline.js'; /** * @typedef {Object} StaggerParameters * @property {Number|String} [start] * @property {Number|'first'|'center'|'last'} [from] * @property {Boolean} [reversed] * @property {Array.<Number>} [grid] * @property {('x'|'y')} [axis] * @property {EasingParam} [ease] * @property {TweenModifier} [modifier] */ /** * @callback StaggerFunction * @param {Target} [target] * @param {Number} [index] * @param {Number} [length] * @param {Timeline} [tl] * @return {Number|String} */ /** * @param {Number|String|[Number|String,Number|String]} val * @param {StaggerParameters} params * @return {StaggerFunction} */ export const stagger = (val, params = {}) => { let values = []; let maxValue = 0; const from = params.from; const reversed = params.reversed; const ease = params.ease; const hasEasing = !isUnd(ease); const hasSpring = hasEasing && !isUnd(/** @type {Spring} */(ease).ease); const staggerEase = hasSpring ? /** @type {Spring} */(ease).ease : hasEasing ? parseEasings(ease) : null; const grid = params.grid; const axis = params.axis; const fromFirst = isUnd(from) || from === 0 || from === 'first'; const fromCenter = from === 'center'; const fromLast = from === 'last'; const isRange = isArr(val); const val1 = isRange ? parseNumber(val[0]) : parseNumber(val); const val2 = isRange ? parseNumber(val[1]) : 0; const unitMatch = unitsExecRgx.exec((isRange ? val[1] : val) + emptyString); const start = params.start || 0 + (isRange ? val1 : 0); let fromIndex = fromFirst ? 0 : isNum(from) ? from : 0; return (_, i, t, tl) => { if (fromCenter) fromIndex = (t - 1) / 2; if (fromLast) fromIndex = t - 1; if (!values.length) { for (let index = 0; index < t; index++) { if (!grid) { values.push(abs(fromIndex - index)); } else { const fromX = !fromCenter ? fromIndex % grid[0] : (grid[0] - 1) / 2; const fromY = !fromCenter ? floor(fromIndex / grid[0]) : (grid[1] - 1) / 2; const toX = index % grid[0]; const toY = floor(index / grid[0]); const distanceX = fromX - toX; const distanceY = fromY - toY; let value = sqrt(distanceX * distanceX + distanceY * distanceY); if (axis === 'x') value = -distanceX; if (axis === 'y') value = -distanceY; values.push(value); } maxValue = max(...values); } if (staggerEase) values = values.map(val => staggerEase(val / maxValue) * maxValue); if (reversed) values = values.map(val => axis ? (val < 0) ? val * -1 : -val : abs(maxValue - val)); } const spacing = isRange ? (val2 - val1) / maxValue : val1; const offset = tl ? parseTimelinePosition(tl, isUnd(params.start) ? tl.iterationDuration : start) : /** @type {Number} */(start); /** @type {String|Number} */ let output = offset + ((spacing * round(values[i], 2)) || 0); if (params.modifier) output = params.modifier(output); if (unitMatch) output = `${output}${unitMatch[2]}`; return output; } }