<div class="section">
<div class="cover">
<div class="slider-box">
<div class="slider">
<div class="slide"><span>1 / 3</span></div>
<div class="slide"><span>2 / 3</span></div>
<div class="slide"><span>3 / 3</span></div>
</div>
</div>
</div>
<div class="related">
<div class="related-header">
Заголовок
</div>
<div class="full-set">
<div class="set active">
<div class="block one">предмет 1 блока 1</div>
<div class="block two">предмет 2 блока 1</div>
<div class="block three">предмет 3 блока 1</div>
</div>
<div class="set">
<div class="block one">предмет 1 блока 2</div>
<div class="block two">предмет 2 блока 2</div>
<div class="block three">предмет 3 блока 2</div>
</div>
<div class="set">
<div class="block one">предмет 1 блока 3</div>
<div class="block two">предмет 2 блока 3</div>
<div class="block three">предмет 3 блока 3</div>
</div>
</div>
</div>
</div>
body {
padding: 0;
margin: 0;
}
.slider-box, .slide {
width: 80vw;
height: 200px;
}
.slider-box {
position: relative;
margin: 0 auto;
overflow: hidden;
}
.slider-box, .slider, .slide, .slider-btn, .slider-pagination, .set {
display: flex;
}
.slide, .slider-btn {
align-items: center;
justify-content: center;
}
.slider-btn {
position: absolute;
top: 50%;
width: 20px;
height: 20px;
background: #000;
color: #fff;
}
.slider-btn.previous {
left: 0;
}
.slider-btn.next {
right: 0;
}
.slider-pagination {
position: absolute;
bottom: 5px;
left: 50%;
transform: translateX(-40%);
}
.slider-point {
width: 5px;
height: 5px;
margin-right: 10px;
border-radius: 50%;
border: 1px solid #000;
}
.related-header {
text-align: center;
margin: 10px 0;
}
.set {
display: none;
justify-content: space-around;
padding: 10px;
}
.slider-box, .set, .block {
box-shadow: inset 0 0 1px 1px #000;
}
.block {
width: 100px;
height: 100px;
}
.set.active {
display: flex;
}
class Slider {
constructor(slider) {
this.currentImg = 0;
this.speed = 500;
this.swipeStatus = this.swipeStatus.bind(this);
this.keyboardHandler = this.keyboardHandler.bind(this);
this.scrollImages = this.scrollImages.bind(this);
this.previousImage = this.previousImage.bind(this);
this.nextImage = this.nextImage.bind(this);
this.slider = $(slider);
this.slider
.parent()
.attr("tabIndex", 0)
.on("blur focus click", this.keyboardHandler)
.swipe({
triggerOnTouchEnd: true,
triggerOnTouchLeave: true,
swipeStatus: this.swipeStatus,
allowPageScroll: "vertical",
threshold: 75
});
this.maxImages = this.slider.find(">*").length;
this.imagesOut = ( this.maxImages - this.slider.parent().width() / ( this.slider.find(".slide").width() ) );
if ( 0 < this.imagesOut ) {
this.slider.parent().append('<div class="slider-btn previous"><</div><div class="slider-btn next">></div><div class="slider-pagination"></div>');
const
count = this.slider.find('.slide').length,
html = [Array(count)].map((n, i) => `<div class="slider-point" data-id="${i}"></div>`).join('')
this.slider.parent().find('.slider-pagination').append(html);
}
this.prevBtn = this.slider.parent().find(".slider-btn.previous");
this.nextBtn = this.slider.parent().find(".slider-btn.next");
this.sliderPoint = this.slider.parent().find('.slider-point');
this.prevBtn.on("click", this.previousImage);
this.nextBtn.on("click", this.nextImage);
this.sliderPoint.on('click', e => {
this.currentImg = e.target.dataset.id;
this.scrollImages(this.currentImg, this.speed);
});
}
keyboardHandler(event) {
if (event.type === "focus") {
document.addEventListener("keydown", this.keyboardHandler);
this.constructor.activeInstance = this;
} else if (event.type === "blur") {
document.removeEventListener("keydown", this.keyboardHandler);
this.constructor.activeInstance = null;
} else if (event.type === "keydown") {
if (event.keyCode === 37) this.previousImage();
if (event.keyCode === 39) this.nextImage();
} else {
this.slider.parent().focus();
}
return true;
}
swipeStatus(event, phase, direction, distance) {
//If we are moving before swipe, and we are going L or R in X mode, or U or D in Y mode then drag.
if (phase == "move" && (direction == "left" || direction == "right")) {
var duration = 0;
if (direction == "left") {
this.scrollImages(
this.currentImg + 0.0025 * distance,
duration
);
} else if (direction == "right") {
this.scrollImages(
this.currentImg - 0.0025 * distance,
duration
);
}
} else if (phase == "cancel") {
this.scrollImages(this.currentImg, this.speed);
} else if (phase == "end") {
if (direction == "right") {
this.previousImage();
} else if (direction == "left") {
this.nextImage();
}
}
}
scrollImages(distance, duration) {
this.slider.css("transition-duration", (duration / 1000).toFixed(1) + "s");
this.slider.css("transform", "translate(" + (100 * -distance / this.maxImages) + "%,0)");
var current = this.slider.parent().parent().parent().find('.active');
current.removeClass('active');
this.slider.parents().find('.set').eq(this.currentImg).addClass('active');
}
previousImage() {
if (this.currentImg != '0') {
this.currentImg = Math.max(this.currentImg - 1, 0);
this.scrollImages(this.currentImg, this.speed);
} else {
this.currentImg = this.maxImages - 1;
this.scrollImages(this.currentImg, this.speed);
}
}
nextImage() {
if ( 0 < ( this.slider.find(">*").length - ( this.slider.parent().width() / this.slider.find(".slide").width() ) )) {
const maxImages = ( this.slider.find(">*").length - ( this.slider.parent().width() / this.slider.find(".slide").width() ) );
this.currentImg = Math.min(this.currentImg + 1, maxImages);
this.scrollImages(this.currentImg, this.speed);
}
else {
this.currentImg = Math.max(this.currentImg - 1, 0);
this.scrollImages(this.currentImg, this.speed);
}
}
}
$(() => {
for (const element of $(".slider")) {
new Slider(element);
}
});
This Pen doesn't use any external CSS resources.