31.12.2019, 15:25
|
Новичок на форуме
|
|
Регистрация: 31.12.2019
Сообщений: 5
|
|
Слайдер карусель
Всем привет. Есть конструктор слайдера-карусели, сейчас пытаюсь добавить точки и обозначение типа "01/04" в зависимости от текущего сайта. Направьте на правильный путь, начал с точками, но работает некорректно. Спасибо
<div class="carousel-container">
<div class="carousel-slides">
<img class="slide" id="lastClone" src="4.jpg">
<img class="slide" src="1.jpg">
<img class="slide" src="2.jpg">
<img class="slide" src="3.jpg">
<img class="slide" src="4.jpg">
<img class="slide" id="firstClone" src="1.jpg">
</div>
<div class="btn-container">
<div class="btn" id="prev"> prev </div>
<div class="btn" id="next"> next </div>
</div>
<div class="dots-container">
<div class="dot active"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</div>
.carousel-container {
display: block;
width: 640px;
height: 320px;
margin: 0 auto;
overflow: hidden;
position: relative;
}
.carousel-slides {
width: 100%;
height: 100%;
position: relative;
top: 0;
left: 0;
}
img {
width: 100%;
height: 100%;
}
.slide {
position: absolute;
top: 0;
}
.slide:nth-child(1) {
left: 0;
}
.slide:nth-child(2) {
left: 100%;
}
.slide:nth-child(3) {
left: 200%;
}
.slide:nth-child(4) {
left: 300%;
}
.slide:nth-child(5) {
left: 400%;
}
.slide:nth-child(6) {
left: 500%;
}
.btn-container {
display: flex;
justify-content: space-between;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
background-color: rgba(255,138,24,0.5);
}
.btn {
font-size: 24px;
font-weight: 600;
padding: 10px;
cursor: pointer;
}
.dots-container {
position: absolute;
right: 20px;
top: 80px;
}
.dot {
width: 20px;
height: 20px;
border: 1px solid #fff;
border-radius: 50%;
margin: 20px;
cursor: pointer;
}
.active {
background-color: red;
}
//Создаем шаблон
(function(){
//Для document и индекса создаем переменные
var doc = document,
index = 1;
//Определяем конструктор слайдера
var Slider = function() {
//Определяем контейнер слайдера как свойство
this.box = doc.querySelector('.carousel-container');
//Определяем контейнер-обертку слайдов как свойство
this.slidesBox = doc.querySelector('.carousel-slides');
//Определяем непосредственно слайды как свойства
this.slides = doc.querySelectorAll('.slide');
//Определяем кнопки как свойства
this.btns = doc.querySelectorAll('.btn');
//Получаем значение ширины главного контейнера
this.size = this.box.clientWidth;
//Определяем точки
this.dots = doc.querySelectorAll('.dot');
//Вызываем методы внутри контейнера
this.position();
this.carousel();
this.currentSlide();
}
//Создаем методы для слайдера
//1. Метод для перемещения картинок на одну влево, чтобы первая картинка оказалась на своем месте
Slider.prototype.position = function() {
var size = this.size;
this.slidesBox.style.transform = `translateX(${-index * size}px)`;
};
//2. Метод переключения
Slider.prototype.carousel = function() {
var i, max = this.btns.length,
that = this;
for(i = 0; i < max; i += 1) {
that.btns[i].addEventListener('click', Slider[that.btns[i].id].bind(null, that))//Slider[id кнопок, для вызова статических методов] bind - передача аргументов в статические функции, т.к. статические методы не имеют доступа в пространство конструктора, не видят его свойства
}
};
//3. Создаем статичные методы для кнопок
Slider.prev = function(box) {
box.slidesBox.style.transition = 'transform .3s ease-in-out';
var size = box.size;
var dots = box.dots;
index <= 0 ? false : index--;
box.slidesBox.style.transform = `translateX(${-index * size}px)`;
for(var i = 0; i < dots.length; i += 1) {
dots[i].classList.remove('active');
}
index <= 0 ? false : dots[index - 1].classList.add('active');
box.jump();
};
Slider.next = function(box) {
box.slidesBox.style.transition = 'transform .3s ease-in-out';
var max = box.slides.length;
var size = box.size;
var dots = box.dots;
index >= max - 1 ? false : index++;
box.slidesBox.style.transform = `translateX(${-index * size}px)`;
for(var i = 0; i < dots.length; i += 1) {
dots[i].classList.remove('active');
}
index >= max - 1 ? false : dots[index - 1].classList.add('active');
box.jump();
};
//Создаем метод для плавного перехода изображений
Slider.prototype.jump = function() {
var that = this;
var size = this.size;
this.slidesBox.addEventListener('transitionend', function() {
that.slides[index].id === 'firstClone' ? index = 1 : index;
that.slides[index].id === 'lastClone' ? index = that.slides.length - 2 : index;
that.slidesBox.style.transition = 'none';
that.slidesBox.style.transform = `translateX(${-index * size}px)`;
});
};
Slider.prototype.currentSlide = function() {
var i, dots = this.dots;
var that = this;
for(i = 0; i < dots.length; i += 1) {
dots[i].addEventListener('click', function() {
that.carousel();
});
}
};
//Вызываем конструктор
new Slider();
})();
|
|
31.12.2019, 19:30
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
img {
width: 100%;
height: 100%;
object-fit: cover; /* нужно указать, чтобы не было «искажения» картинок */
}
/* ... удивительно, а если будет 104 картинки? */
.slide:nth-child(2) {
left: 100%;
}
.slide:nth-child(3) {
left: 200%;
}
.slide:nth-child(4) {
left: 300%;
}
.slide:nth-child(5) {
left: 400%;
}
.slide:nth-child(6) {
left: 500%;
}
Вам нужно избавиться от повтора в исходном коде… удалите…
<img class="slide" id="lastClone" src="4.jpg">
<img class="slide" id="firstClone" src="1.jpg">
Это вообще бессмысленно...
//Для document и индекса создаем переменные
var doc = document,
index = 1;
Должно ведь быть описано внутри класса…
//Вызываем конструктор
new Slider();
А если ещё раз вызвать, то как будет другой экземпляр работать?
Короче, вот сделал кучу исправлений... не буду их описывать, сравни, если надо, но если что-то не понятно, то можно ещё спросить в этой же теме!
https://codepen.io/Malleys/pen/YzPrEwP
|
|
31.12.2019, 19:38
|
Новичок на форуме
|
|
Регистрация: 31.12.2019
Сообщений: 5
|
|
Спасибо. Работает.
Перешли, пожалуйста, в виде архива, CodePan лагает, не вижу код.
|
|
31.12.2019, 19:44
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Странно! А экспорт тоже не работает(правый нижний угол)?
|
|
31.12.2019, 20:05
|
Новичок на форуме
|
|
Регистрация: 31.12.2019
Сообщений: 5
|
|
Экспорта тоже не видно. Не знаю в чем дело...
По коду, все работает, только немного некорректно отображается, кнопки слетели, и 1 of 4 вроде..
Сейчас буду разбираться, спасибо огромное. Ну у тебя тут как-то более профессионально написано
|
|
31.12.2019, 20:12
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Malleys,
почему
Math.mod = function mod(a, b) {
return (a % b + b) % b;
};
а не
Math.mod = function mod(a, b) {
return (a + b) % b;
};
?
|
|
01.01.2020, 10:04
|
Новичок на форуме
|
|
Регистрация: 31.12.2019
Сообщений: 5
|
|
Сообщение от Rise
|
faceVB,
Обратные кавычки для строк это ES6, почему тогда остальной код в ES5, где class, let, const, for...of?
|
Ну я думаю, не в этом проблема. Все работало с ними.
|
|
01.01.2020, 12:22
|
Новичок на форуме
|
|
Регистрация: 31.12.2019
Сообщений: 5
|
|
Согласен. Точки не могу внедрить без ошибок. Может подскажете, что не так с кодом в первом сообщении. Кстати, С Новым Годом!
|
|
01.01.2020, 15:46
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
слайдер с точечной навигацией
faceVB,
Malleys,
как вариант ...
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<style type="text/css">
@import url('https://fonts.googleapis.com/css?family=Parisienne&display=swap');
.carousel-container {
display: block;
width: 640px;
height: 320px;
margin: 0 auto;
position: relative;
overflow: hidden;
background: black;
}
.carousel-slides {
width: 100%;
height: 100%;
}
.carousel-slides > * {
width: 100%;
height: 100%;
object-fit: cover;
position: absolute;
transition: transform 1.8s cubic-bezier(0.165, 0.84, 0.44, 1);
transform: translateX(-100%);
}
.carousel-container:hover .btn-container {
opacity: 1;
transform: translateY(0%);
}
.btn-container {
display: flex;
justify-content: space-between;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
background-color: rgba(133, 194, 255, .3);
z-index: 2;
opacity: 0;
transform: translateY(100%);
transition: .4s;
}
.btn-container > button {
background: transparent;
border: 0;
padding: 10px;
cursor: pointer;
font: 400 2.4em / 23px "Parisienne", sans-serif;
color: #FFFFFF;
}
.btn-container > .info {
display: grid;
place-content: center;
}
.dots-container {
position: absolute;
right: 20px;
top: 0;
bottom: 54px;
z-index: 2;
height: max-content;
margin: auto;
display: flex;
flex-direction: column;
}
.dots-container > .dot {
-webkit-appearance: none;
appearance: none;
width: 1em;
height: 1em;
border: 1px solid #fff;
border-radius: 50%;
cursor: pointer;
display: flex;
margin: 3px;
filter: drop-shadow(0 0 2px black);
}
.dots-container > .dot:checked {
background-color: rgba(240, 255, 240, .8);
border: transparent;
}
.dots-container > .dot:focus, .btn-container > button {
outline: none;
}
.info{
color: #FFFFFF;
font: 400 1.2em / 23px "Parisienne", sans-serif;
}
</style>
</head>
<body>
<div class="carousel-container">
<div class="carousel-slides">
<img src="https://picsum.photos/640/320?1">
<img src="https://picsum.photos/640/320?2">
<img src="https://picsum.photos/640/320?3">
<img src="https://picsum.photos/640/320?4">
<img src="https://picsum.photos/640/320?5">
<img src="https://picsum.photos/640/320?6">
<img src="https://picsum.photos/640/320?7">
<img src="https://picsum.photos/640/320?8">
</div>
<div class="btn-container">
<button data-step="-1"><</button>
<section class="info">1 of 4</section>
<button data-step="1">></button>
</div>
<div class="dots-container"></div>
</div>
<script>
(function() {
function Slider(carouselContainer) {
this.slides = Array.from(carouselContainer.querySelectorAll(".carousel-slides > *"));
this.btns = carouselContainer.querySelector(".btn-container");
this.info = carouselContainer.querySelector(".btn-container > .info");
var dotsContainer = carouselContainer.querySelector(".dots-container");
this.currentSlider = this.slides[1];
this.dots = this.slides.map(function(slide, index) {
var dot = document.createElement("input");
dot.type = "radio";
dot.name = "slider-" + Slider.id;
dot.className = "dot";
dot.setAttribute("data-slide", index);
dotsContainer.appendChild(dot);
return dot;
});
this.btns.addEventListener("click", (function(event) {
var button = event.target.closest("[data-step]");
if(!button) return;
var step = Number(button.getAttribute("data-step"));
this.go(Math.mod(this.index + step, this.slides.length));
}).bind(this));
dotsContainer.addEventListener("change", (function(event) {
var index = Number(event.target.getAttribute("data-slide"));
this.go(index);
}).bind(this));
this.index = 0;
this.go(0);
Slider.id++;
}
Slider.id = 0;
Slider.prototype.go = function(index) {
var X = index > this.index ? 100 : -100;
if(!index && this.index == this.slides.length - 1) X = 100;
if(index == this.slides.length - 1 && !this.index) X = -100;
this.index = index;
this.dots[this.index].checked = true;
this.info.textContent = (this.index + 1) + " of " + this.slides.length;
this.nextSlider = this.slides[this.index];
this.nextSlider.style.transition = "none";
this.nextSlider.style.transform = `translateX(${X}%)`;
document.documentElement.clientWidth;
this.nextSlider.style.transition = "";
this.nextSlider.style.transform = `translateX(0%)`;
this.currentSlider.style.transform = `translateX(${-X}%)`;
[this.currentSlider, this.nextSlider] = [this.nextSlider, this.currentSlider];
};
Math.mod = function mod(a, b) {
return (a + b) % b;
};
Array.from(document.querySelectorAll(".carousel-container")).forEach(function(container) {
new Slider(container);
});
})();
</script>
</body>
</html>
Последний раз редактировалось рони, 01.01.2020 в 18:13.
|
|
01.01.2020, 16:01
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Сообщение от Malleys
|
https://codepen.io/Malleys/pen/YzPrEwP
|
эффект смены слайдов, 3 варианта
смена одного слайда на другой
1 без анимации (нажать 1 и 3 точку попеременно)
2 анимация только одного (нажимать последовательно на точки)
3 нормальная (вероятно только после прогона по всем слайдам, кнопками next или prev)
может как-то единообразно сделать?
|
|
|
|