Карусель на Vanilla.JS. Часть 2

от автора

Доброго времени суток. Сегодня мы добавим следующие возможности в наш слайдер:

  • Зацикленность карусели;
  • Автоматическое переключение слайдов;
  • Тач-события;
  • События мыши.

Первая часть находиться здесь.
Разметка карусели и её стили оставим прежними. А вот 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *