Skip to content

Утилиты ​

Небольшие самостоятельные помощники, которые используются внутри движков выше, и экспортируются для повторного использования в своих эффектах.

Перевод значения между диапазонами ​

mapRange() — линейно переводит значение из одного диапазона в другой.

ts
function mapRange(
  value: number,
  from: [number, number],
  to: [number, number],
  clampResult?: boolean,
): number

Параметры ​

value ​

number · по умолчанию: —

Значение для преобразования, выраженное в диапазоне from.

from ​

[number, number] · по умолчанию: —

Входной диапазон, в котором сейчас выражено value.

to ​

[number, number] · по умолчанию: —

Выходной диапазон, в который нужно преобразовать значение.

clampResult ​

boolean · по умолчанию: false

При true держит результат в пределах to на краях, вместо экстраполяции за них — корректно обрабатывает и перевёрнутый диапазон to (например, [100, -100]).

Возвращаемое значение ​

number — преобразованное значение.

Пример:

ts
import { mapRange } from '@macrulez/inview-core'

mapRange(0.5, [0, 1], [0, 200]) // 100
mapRange(1.2, [0, 1], [0, 200], true) // 200 (ограничено)

Привязка к CSS-переменной ​

bindCSSVar() — записывает числовое значение прогресса в CSS custom property на элементе, чтобы результирующий визуальный эффект можно было собрать на чистом CSS.

ts
function bindCSSVar(element: HTMLElement, name: string, value: number | string): void

Параметры ​

element ​

HTMLElement · по умолчанию: —

name ​

string · по умолчанию: —

Имя custom property. Если name ещё не начинается с --, префикс добавляется автоматически.

value ​

number | string · по умолчанию: —

Возвращаемое значение ​

void

Пример:

ts
import { bindCSSVar } from '@macrulez/inview-core'

bindCSSVar(el, 'progress', 0.42) // el.style.setProperty('--progress', '0.42')
css
.card {
  opacity: var(--progress);
}

Предпочтение сниженной анимации ​

prefersReducedMotion() — читает медиа-запрос prefers-reduced-motion.

ts
function prefersReducedMotion(): boolean

Возвращаемое значение ​

boolean — false, если window/matchMedia недоступны (SSR), иначе window.matchMedia('(prefers-reduced-motion: reduce)').matches.

Одноразовая проверка — не замечает изменение настройки ОС посреди сессии, если что-то ещё не вызовет её заново. Для реактивного значения, обновляющегося на событие change медиа-запроса, используйте usePrefersReducedMotion():

ts
function usePrefersReducedMotion(): Ref<boolean> // Vue
function usePrefersReducedMotion(): boolean // React
vue
<script setup lang="ts">
import { usePrefersReducedMotion } from '@macrulez/inview-vue'

const reduced = usePrefersReducedMotion()
</script>

Vue composable подписывается на событие change медиа-запроса и отписывается при размонтировании, возвращая Ref<boolean>; про React-хук (построенный на useSyncExternalStore) — см. React-хуки.

Прокрутка к элементу ​

scrollToElement() — плавно скроллит контейнер (по умолчанию window) так, чтобы элемент оказался у его края, со смещением в пикселях — случай «доскроллить до элемента», который ScrollEngine.scrollTo сам по себе не покрывает (он принимает только сырую позицию x/y, а не элемент).

ts
function scrollToElement(el: Element, options?: ScrollToElementOptions): void

Параметры ​

el ​

Element · по умолчанию: —

options ​

ScrollToElementOptions · по умолчанию: {}

ПолеТипПо умолчанию
targetWindow | HTMLElementwindow
offsetnumber0 — зазор в пикселях между краем элемента и краем контейнера
axis'x' | 'y''y'
behavior'auto' | 'smooth''smooth', если только prefersReducedMotion() не вернул true — тогда 'auto'

Возвращаемое значение ​

void

Использует нативную анимацию плавного скролла браузера, а не рукописный rAF-цикл — поэтому duration/easing не настраиваются, вместо этого передайте behavior: 'auto' для мгновенного прыжка.

Пример:

ts
import { scrollToElement } from '@macrulez/inview-core'

scrollToElement(sectionEl, { offset: 80 }) // например, чтобы не перекрыть sticky-шапку

useScrollTo (Vue) ​

ts
function useScrollTo(
  target?: MaybeRefOrGetter<Window | HTMLElement | null | undefined>,
): (el: Element | null | undefined, options?: UseScrollToOptions) => void

Возвращает колбэк scrollTo(el, options?), привязанный к target (по умолчанию window). target принимает ref/геттер и перечитывается через toValue() при каждом вызове — если реф позже указывает на другой контейнер, это подхватывается автоматически, без повторного вызова useScrollTo().

vue
<script setup lang="ts">
import { useScrollTo } from '@macrulez/inview-vue'

const scrollTo = useScrollTo()
</script>

<template>
  <button @click="scrollTo(sectionEl, { offset: 80 })">Перейти</button>
</template>

Про React-хук — см. React-хуки; там target — обычное значение, захваченное в массиве зависимостей useCallback, так что новый target даёт новый колбэк вместо перечитывания вживую.

Ограничение значения ​

clamp() — ограничивает значение диапазоном [min, max].

ts
function clamp(value: number, min: number, max: number): number

Параметры ​

value ​

number · по умолчанию: —

min ​

number · по умолчанию: —

max ​

number · по умолчанию: —

Возвращаемое значение ​

number — value, ограниченное диапазоном [min, max].

Задержка стаггера ​

staggerDelay() — вычисляет CSS transition-delay для index-го элемента в стаггер-эффекте (плитка/список появляются один за другим), вместо того чтобы писать Math.min(i, max) * step руками в каждом месте вызова.

ts
function staggerDelay(index: number, options?: StaggerDelayOptions): string

Параметры ​

index ​

number · по умолчанию: —

Позиция элемента в последовательности (с нуля).

options ​

StaggerDelayOptions · по умолчанию: {}

ПолеТипПо умолчанию
stepnumber60 — задержка в мс на один шаг
maxnumberInfinity — ограничивает эффективный индекс, чтобы 50-й элемент не ждал почти секунду
unit'ms' | 's''ms'
mode'linear' | 'cycle''linear' — на max рост выравнивается. 'cycle' возвращается к 0 после max, повторяющейся волной

Возвращаемое значение ​

string — CSS-значение времени (например, '180ms', '1s').

Пример:

ts
import { staggerDelay } from '@macrulez/inview-core'

staggerDelay(3) // '180ms'
staggerDelay(10, { step: 70, max: 4 }) // '280ms' — индекс ограничен четвёркой
staggerDelay(2, { step: 500, unit: 's' }) // '1s'

// mode: 'cycle' возвращается к 0 после max вместо выравнивания —
// повторяющаяся волна (0, 70, 140, 210, 0, 70, 140, 210, ...) для
// длинного списка/сетки, вместо того чтобы всё после индекса 3 делило
// одну задержку:
staggerDelay(5, { step: 70, max: 3, mode: 'cycle' }) // '70ms' — индекс 5 оборачивается в тот же слот, что индекс 1

Опция stagger у createRevealController построена поверх этой функции — вызывайте её напрямую для самостоятельно написанного стаггер-эффекта в v-for/.map() вместо контроллера.

useStagger (Vue) ​

ts
function useStagger(
  index: MaybeRefOrGetter<number>,
  options?: MaybeRefOrGetter<StaggerDelayOptions | undefined>,
): ComputedRef<string>

Обёртка computed, пересчитывающая значение при изменении index/options (как ref/геттера), вместо вызова staggerDelay() руками в каждом месте самостоятельно написанного стаггер-эффекта в v-for.

vue
<script setup lang="ts">
import { useStagger } from '@macrulez/inview-vue'

const delay = useStagger(index, { step: 70, max: 4 })
</script>

<template>
  <div class="reveal" :style="{ transitionDelay: delay }" />
</template>

Про React-хук — см. React-хуки; тонкая, не мемоизированная обёртка — вычисление достаточно дешёвое, чтобы просто вызывать его каждый рендер.

Пресеты плавности ​

easings — набор пресетов плавности, применяемых к значению прогресса 0..1 перед тем, как передать его в эффект (смещение параллакса, CSS-переменную и т. д.).

ts
type Easing = (t: number) => number

const easings: Record<EasingName, Easing>
type EasingName = keyof typeof easings

Имена пресетов: linear, easeInQuad, easeOutQuad, easeInOutQuad, easeInCubic, easeOutCubic, easeInOutCubic, easeInSine, easeOutSine, easeInOutSine.

Пример:

ts
import { easings } from '@macrulez/inview-core'

const eased = easings.easeOutCubic(0.5)