Библиотека Driver.js используется для создания интерактивных туров по интерфейсу. В контексте Svelte она легко интегрируется благодаря минималистичной архитектуре и отсутствию необходимости в сложной настройке.
Установка через пакетный менеджер:
npm install driver.js
Подключение стилей (обязательно):
import 'driver.js/dist/driver.css';
Импорт библиотеки в Svelte-компоненте:
import Driver from 'driver.js';
Инициализация экземпляра:
const driver = new Driver();
Svelte использует реактивную модель, поэтому важно учитывать жизненный цикл компонента. Инициализация Driver.js должна происходить после монтирования DOM.
Использование onMount:
import { onMount } from 'svelte';
import Driver from 'driver.js';
import 'driver.js/dist/driver.css';
let driver;
onMount(() => {
driver = new Driver({
animate: true,
opacity: 0.75,
padding: 10
});
});
Driver.js работает через массив шагов, каждый из которых описывает элемент и подсказку.
Пример:
const steps = [
{
element: '#header',
popover: {
title: 'Заголовок',
description: 'Это основной заголовок страницы',
position: 'bottom'
}
},
{
element: '#button',
popover: {
title: 'Кнопка',
description: 'Нажмите для выполнения действия',
position: 'right'
}
}
];
Запуск тура:
driver.defineSteps(steps);
driver.start();
HTML-разметка:
<h1 id="header">Главная</h1>
<button id="button">Начать</button>
Важно: элементы должны существовать в DOM к моменту запуска тура. В противном случае Driver.js не сможет найти их.
Часто тур запускается по действию пользователя:
<button on:click={startTour}>Показать тур</button>
function startTour() {
driver.defineSteps(steps);
driver.start();
}
Svelte позволяет динамически изменять шаги через реактивные переменные:
let steps = [];
$: if (dataLoaded) {
steps = [
{
element: '#dynamic',
popover: {
title: 'Динамический элемент',
description: 'Появился после загрузки данных'
}
}
];
}
Важно повторно вызывать defineSteps, если шаги
изменяются:
$: if (steps.length) {
driver.defineSteps(steps);
}
В Svelte элементы могут появляться после загрузки данных или условий
({#if}).
Пример:
{#if showElement}
<div id="dynamic">Контент</div>
{/if}
Запуск тура после появления элемента:
import { tick } from 'svelte';
async function startTour() {
showElement = true;
await tick();
driver.defineSteps(steps);
driver.start();
}
tick() гарантирует, что DOM обновлён.
Driver.js предоставляет множество настроек:
driver = new Driver({
className: 'custom-theme',
animate: true,
opacity: 0.6,
allowClose: true,
overlayClickNext: false
});
Кастомные стили:
.custom-theme .driver-popover {
background-color: #1e1e1e;
color: #fff;
}
.custom-theme .driver-popover-title {
font-weight: bold;
}
Driver.js поддерживает хуки:
driver = new Driver({
onHighlightStarted: (element) => {
console.log('Начало подсветки:', element);
},
onDestroyed: () => {
console.log('Тур завершён');
}
});
Использование в Svelte:
onMount(() => {
driver = new Driver({
onDestroyed: () => {
completed = true;
}
});
});
Состояние можно хранить в Svelte store:
import { writable } from 'svelte/store';
export const tourCompleted = writable(false);
Обновление состояния:
driver = new Driver({
onDestroyed: () => {
tourCompleted.set(true);
}
});
В Svelte удобно оборачивать логику в action:
export function tour(node, options) {
const driver = new Driver(options);
return {
update(newOptions) {
driver.setOptions(newOptions);
},
destroy() {
driver.destroy();
}
};
}
Использование:
<div use:tour={{ animate: true }}></div>
При использовании SvelteKit важно учитывать смену страниц. Тур можно запускать после навигации:
import { afterNavigate } from '$app/navigation';
afterNavigate(() => {
driver.start();
});
Чтобы не загружать Driver.js сразу:
let driver;
async function initDriver() {
const module = await import('driver.js');
driver = new module.default();
}
Сохранение прогресса:
localStorage.setItem('tourCompleted', 'true');
Проверка:
if (!localStorage.getItem('tourCompleted')) {
driver.start();
}
Частые проблемы:
Элемент не найден
tick()Тур не запускается
console.log(steps)Стили не применяются
driver.cssdriver.destroy();
const steps = [
user.isAdmin && {
element: '#admin',
popover: {
title: 'Админ-панель'
}
}
].filter(Boolean);
Если элементы находятся в дочерних компонентах:
iddriver.moveNext();
driver.movePrevious();
driver.reset();
Пример структуры:
/lib/tour/
steps.js
driver.js
store.js
import { onMount, tick } from 'svelte';
import Driver from 'driver.js';
import 'driver.js/dist/driver.css';
let driver;
const steps = [
{
element: '#title',
popover: {
title: 'Заголовок',
description: 'Описание'
}
}
];
onMount(() => {
driver = new Driver({
animate: true
});
});
async function startTour() {
await tick();
driver.defineSteps(steps);
driver.start();
}
<h1 id="title">Пример</h1>
<button on:click={startTour}>Старт</button>
tick() — ключевой инструмент синхронизации