Доброго времени суток. Сегодня мы добавим следующие возможности в наш слайдер:
- Зацикленность карусели;
- Автоматическое переключение слайдов;
- Тач-события;
- События мыши.
Первая часть находиться здесь.
Разметка карусели и её стили оставим прежними. А вот JS перепишем.
Начнём с создания возобновляймого таймера:
function Timer(callback, delay) { /* Private properties */ let timerId, start, remaining = delay; /* Public methods */ this.resume = () => { start = new Date(); timerId = setTimeout(() => { remaining = delay; this.resume(); callback(); }, remaining); }; this.pause = () => { clearTimeout(timerId); remaining -= new Date() - start; }; this.become = () => { clearTimeout(timerId); remaining = delay; this.resume(); }; /* Constructor */ this.resume(); }
Теперь напишем функцию-конструктор карусели, её приватные свойства и методы:
function Carousel(setting) { /* Scope private methods and properties */ let private = {}; /* Private properties */ private.default = { "touch": true, "autoplay": false, "autoplayDelay": 3000, "pauseOnFocus": true, "pauseOnHover": true }; private.setting = Object.assign(private.default, setting); private.isAnimationEnd = true; private.sel = { "wrap": document.querySelector(private.setting.wrap), "children": document.querySelector(private.setting.wrap).children, "prev": document.querySelector(private.setting.prev), "next": document.querySelector(private.setting.next) }; private.opt = { "position": 0, "max_position": document.querySelector(private.setting.wrap).children.length }; /* Constructor */ // Clone first elem to end wrap private.sel.wrap.appendChild(private.sel.children[0].cloneNode(true)); // Autoplay if(private.setting.autoplay === true) { private.timer = new Timer(this.next_slide, private.setting.autoplayDelay); } // Control if(private.sel.prev !== null) { private.sel.prev.addEventListener('click', () => { this.prev_slide(); }); } if(private.sel.next !== null) { private.sel.next.addEventListener('click', () => { this.next_slide(); }); } // Touch events if(private.setting.touch === true) { private.sel.wrap.addEventListener('touchstart', private.hts, false); private.sel.wrap.addEventListener('touchmove', private.htm, false); } // Pause on hover if(private.setting.autoplay === true && private.setting.pauseOnHover === true) { private.sel.wrap.addEventListener('mouseenter', () => { private.timer.pause(); }); private.sel.wrap.addEventListener('mouseleave', () => { private.timer.become(); }); } private.hts = (e) => { xDown = e.touches[0].clientX; yDown = e.touches[0].clientY; }; private.htm = (e) => { if ( ! xDown || ! yDown ) { return; } var xUp = e.touches[0].clientX; var yUp = e.touches[0].clientY; var xDiff = xDown - xUp; var yDiff = yDown - yUp; if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) { if ( xDiff > 0 ) { this.next_slide(); } else { this.prev_slide(); } } xDown = 0; yDown = 0; }; }
Методы hts и htm нужны для обработки тач-событий. Hts будет вызываться при touchStart. Htm при event touchMove и в зависимости от направления mov’а вызывать метод предыдущего или последующего слайда.
Теперь напишем публичные методы:
// Prev slide this.prev_slide = () => { if(!private.isAnimationEnd) { return; } private.isAnimationEnd = false; --private.opt.position; if(private.opt.position < 0) { private.sel.wrap.classList.add('s-notransition'); private.sel.wrap.style["transform"] = `translateX(-${private.opt.max_position}00%)`; private.opt.position = private.opt.max_position - 1; } setTimeout(() => { private.sel.wrap.classList.remove('s-notransition'); private.sel.wrap.style["transform"] = `translateX(-${private.opt.position}00%)`; }, 10); private.sel.wrap.addEventListener('transitionend', () => { private.isAnimationEnd = true; }); if(private.setting.autoplay === true) { private.timer.become(); } }; // Next slide this.next_slide = () => { if(!private.isAnimationEnd) { return; } private.isAnimationEnd = false; if(private.opt.position < private.opt.max_position) { ++private.opt.position; } private.sel.wrap.classList.remove('s-notransition'); private.sel.wrap.style["transform"] = `translateX(-${private.opt.position}00%)`; private.sel.wrap.addEventListener('transitionend', () => { if(private.opt.position >= private.opt.max_position) { private.sel.wrap.style["transform"] = 'translateX(0)'; private.sel.wrap.classList.add('s-notransition'); private.opt.position = 0; } private.isAnimationEnd = true; }); if(private.setting.autoplay === true) { private.timer.become(); } };
Демо:
Это все! Меньше сторонних либ => меньший трафик для пользователя => скорейшая загрузка страницы.
ссылка на оригинал статьи https://habrahabr.ru/post/327690/
Добавить комментарий