Skip to content

Директива in‑view

Dmitry edited this page Jan 13, 2020 · 1 revision

Директива in-view – необходима если вам нужно отслеживать появление какого-либо элемента в зоне видимости. Она подразделяется на 3 стратегии, каждая из стратегий реализует свой подход к определению нахождения элемента в зоне видимости.

Стратегия Intersection Observer

Работает для всех современных платформ (которые поддерживают Intersection Observer v1). Использует Intersection Observer для отслеживания вхождения элемента в зону видимости.

Стратегия Mutation Observer

Если платформа не поддерживает Intersection Observer то будет использоваться другая стратегия, а точнее, Mutation Observer стратегия. В этом случае директива будет строить карту положений элементов и при изменении DOM дерева эта карта будет перестроена. Когда пользователь скроллит странницу директива смотрит в эту карту и ищет элементы которые вошли в зону видимости.

Стратегия Polling

Используется если в параметры директивы было передано свойство polling: true. Если это свойство передано и платформа не поддерживает Intersection Observer то для определения вхождение элементов в область видимости будет использоваться опрос и метод getBoundingClientRect. Эта стратегия идеально подходит если вам нужно определить вхождение элемента в область видимости и при этом элемент имеет position: fixed или находится внутри другого элемента который тоже скроллиться. Будьте осторожны и не злоупотребляйте этой возможностью, так как она может повлиять на производительность вашего приложения.

Используем директиву

Для начала необходимо проверить что директива подключена через runtime флаг в вашем файле конфигураций, после чего директива будет доступна во всех ваших шаблонах.

runtime() {
	return {
		'directives/in-view': true
	};
}

Устанавливаем директиву на элемент:

< .&__class v-in-view = { &
	threshold: 0.7,
	delay: 2000,
	callback: () => emit('elementInViewport'),
	onEnter: () => emit('elementEnterViewport'),
	onLeave: () => emit('elementLeaveViewport')
} .

Или "руками" (не рекомендуется использовать данный метод):

import { InView } from 'core/component/directives/in-view';

export default class bFullScreenView extends iBlock implements iLockPageScroll {
	@hook('mounted')
	initInView(): void {
		// InView может не иметь adaptee если отсутствует
		// поддержка Mutation Observer и Intersection Observer
		if (!InView) {
			return;
		}

		InView.observe(this.$el, {
			threshold: 0.7,
			delay: 2000,
			once: true,
			callback: () => this.emit('elementInViewport'),
			onEnter: () => this.emit('elementEnterViewport'),
			onLeave: () => this.emit('elementLeaveViewport')
		})
	}
}

Директива так же может принимать массив параметров, правда в таком случае стоит помнить что threshold должен быть разным для каждого из объектов.

< .&__class v-in-view = [{ &
	threshold: 0.7,
	delay: 2000,
	callback: () => emit('elementInViewport'),
	onEnter: () => emit('elementEnterViewport'),
	onLeave: () => emit('elementLeaveViewport')
}, {
	threshold: 0.5,
	delay: 1000,
	callback: () => emit('halfElementInviewport')
}] .

Параметры директивы

Имя Тип Базовое Описание
threshold number 1 Число, указывающее, при каком проценте видимости целевого элемента должен сработать callback. Например threshold установлено в значение 0.25, в этом случае callback функция будет вызываться при появлении в зоне видимости на 25% целевого элемента.
callback Function undefined Функция, которая будет вызвана, если элемент преодолел процент видимости заданный в threshold и был в области видимости отрезок времени заданный в delay.
delay number 0 Время в мс. которое должен быть элемент в области видимости чтобы была вызвана функция переданная в callback.
timeout number 0 [Deprecated] используйте delay.
polling boolean undefined [Mutation Strategy] Если значение true то будет использоваться стратегия опроса.
onEnter Function undefined Функция, которая будет вызвана, если элемент преодолел процент видимости заданный в threshold.
onLeave Function undefined Функция, которая будет вызвана, если элемент стал виден в области видимости на меньший процент чем задано в threshold.
once boolean undefined [Модификатор] Если значение установленно в true то после того как callback был вызван наблюдение за элементом прекратиться (поведение изменчиво в зависимости от removeStrategy).
removeStrategy 'remove' | 'deactivate' 'remove' Как должно прекращаться наблюдение за элементом. В случае remove после того как callback был вызван in-view полностью перестанет отслеживать элемент и удалит ссылку на элемент. В случае с deactivate директива in-view перестанет отслеживать элемент но возобновить отслеживание можно в любой момент времени с помощью метода InView.activate('groupName').
group string 'inView-base' К какой группе отнести элемент, используя имя группы, можно активировать/деактивировать наблюдение.
root (() => HTMLElement) | HTMLElement undefined Относительно какого элемента строить карту положений элементов для Mutation Strategy. Для Intersection Observer можно прочесть здесь
count (() => boolean) | boolean undefined Функция, которая будет вызвана перед вызовом callback и если она вернет результат отличный от true то callback не будет вызван.
wait (() => boolean) undefined Функция, которая будет опрашиваться раз в 100 мс. и если эта функция возвращает результат отличный от true отслеживание элемента не начнется.
handleTransitionEnd boolean undefined [Mutation Strategy] Если установлено в true то на обозреваемый элемент будет установлен обработчик события transitionend и в этом обработчике дополнительно будет вызвана проверка положений элементов.
trackVisibility boolean undefined [Intersection Strategy] Если установлено в true то будет отслеживать действительная видимость элемента, работает только для Intersection Observer v2.

Публичное АПИ

Скорее всего вы не будете использовать его напрямую, необходимость использовать публичное апи напрямую может возникнуть только в очень редких случаях.

Метод Описание
setInstance(instance: ObserverStrategy): void Устанавливает adaptee для адаптера.
isMutation(instance: ObserverStrategy): boolean Является ли переданная стратегия Mutation Observer стратегией.
isIntersection(instance: ObserverStrategy): boolean Является ли переданная стратегия Intersection Observer стратегией.
observe(el: HTMLElement, opts: InitOptions): ObservableElement | false Начинает отслеживать появление элемента в области видимости, вернет false если элемент уже отслеживается или у адаптера нет adaptee.
activate(group: string): void Возобновляет отслеживание указанной группы элементов.
deactivate(group: string): void Приостанавливает отслеживание указанной группы элементов.
stopObserve(el: HTMLElement): boolean Останавливает отслеживание элемента и в зависимости от removeStrategy либо деактивирует элемент, либо удаляет с помощью метода remove.
remove(el: HTMLElement): boolean Удаляет из таблицы элементов in-view. Вернет false если нет adaptee или элемент не отслеживался.
check(): void [Mutation Strategy] Проверяет вхождение элементов в зону видимости.
recalculate(deffer: boolean): void [Mutation Strategy] Перестроит карту позиций элементов, если deffer установлено в true то пересчет будет вызван с задержкой через Async.setTimeout.
call(observable: ObservableElement): void Вызовет callbackфункцию. Вызов этого метода - единственный правильный способ засчитать просмотр элемента вручную.
get(el: HTMLElement): CanUndef<ObservableElement> Вернет объект параметров обозреваемого элемента.
Clone this wiki locally