for some months now, i have decided to learn Vue.js, for that I have decided to choose a projet on whcich i will learn so that my learning experience will be more pratical, I am actually working on a carousel which worked perfectly the way I want with JQUERY but I would like to do it now with Vue.js.
PROBLEM: the problem i am facing now is with the “slider-item”, I have just noticed from the chrome devtool that only one “slider-item” displays and I dont know also how to pass the “active” class to it whenever I click to next img or previous img. To summarize I want the “active” class to be passed to each “slider-item” when the previous button or next button is pressed. I have attached a picture to illustrate what i am trying to achieve, please I need help to solve this cause it will help me understand in solving problem related to carousel in Vue.js
enter image description here
// carousel items
const carousels = [
{
img: 'https://www.static-src.com/siva/asset//02_2022/GI-JAN-2022-2000x500-desktop-16feb.jpg?w=960',
href: "#"
},
{
img: 'https://www.static-src.com/siva/asset//02_2022/bliresto-feb22-blm-carousel-desktop-2000x500_desktop_16feb.jpg?w=960',
href: "#"
},
{
img: 'Home-Desk-Hometronics-Valentine-12-13-Feb-22.jpg',
href: "#"
},
{
img: 'https://www.static-src.com/siva/asset//02_2022/rabcan-homepage2000x500-desktop-16feb.jpg?w=960',
href: "#"
}
];
// vue
new Vue({
el: '#app',
data: {
carouselName: 'carousel-next',
carousels: carousels,
len: 0,
show: 0,
xDown: null, // for swiper
yDown: null, // for swiper
autoplay: false,
timer: null, // auto play
timerDelay: 3000,
toggleTimer: true, // pause auto play
minHeight: 0
},
methods: {
toNext() {
this.carouselName = 'carousel-next';
this.show + 1 >= this.len ? this.show = 0 : this.show = this.show + 1;
},
toPrev() {
this.carouselName = 'carousel-prev';
this.show - 1 < 0 ? this.show = this.len - 1 : this.show = this.show - 1;
},
// swiper event(for mobile)
touchStart(e) {
this.xDown = e.touches[0].clientX;
this.yDown = e.touches[0].clientY;
},
touchMove(e) {
const _this = this;
if(!this.xDown || !this.yDown) { return; }
let xUp = e.touches[0].clientX;
let yUp = e.touches[0].clientY;
let xDiff = this.xDown - xUp;
let yDiff = this.yDown - yUp;
if(Math.abs(xDiff) > Math.abs(yDiff)) {
xDiff > 0 ? _this.toNext() : _this.toPrev();
}
this.xDown = null;
this.yDown = null;
},
//
autoPlay() {
setInterval(() => {
if(this.toggleTimer) this.toNext();
}, this.timerDelay);
}
},
mounted() {
this.len = this.carousels.length;
this.autoplay = this.$refs.carousel.dataset.auto == 'true';
this.timerDelay = Number(this.$refs.carousel.dataset.delay) || 3000;
if(this.autoplay) this.autoPlay();
window.addEventListener('load', () => {
this.minHeight = this.$refs.carousel.offsetHeight + 'px';
});
},
});
*, *::before, *::after {
box-sizing: border-box;
}
.slide-placeholder {
position: relative;
}
@media screen and (min-width: 769px), print{
.slide-placeholder {
min-height: 190px;
margin-bottom: 16px;
}
}
.slide-placeholder:before {
content: '';
width: 100%;
background: #0095da;
position: absolute;
top: 0;
}
.slide-placeholder__carousel-container {
position: relative;
margin: 0 auto;
width: 100%;
background-size: cover;
background-repeat: no-repeat;
overflow: hidden;
}
.carousel-container__background {
width: 100%;
height: 100%;
background-size: 100% 100%;
background-position: top;
background-repeat: no-repeat;
position: absolute;
-webkit-filter: blur(20px);
filter: blur(20px);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
-webkit-transform: scale(1.2);
transform: scale(1.2);
opacity: 90%;
}
.custom__container {
width: 100%;
position: relative;
}
.slide-placeholder__carousel-container .custom__container {
max-width: 1200px;
margin: 0 auto;
padding: 10px 0;
}
.carousel-container {
width: 100%;
height: 100%;
overflow: hidden;
}
.carousel-container .items {
height: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.carousel-container .items.placeholder-slider {
margin: 10px auto;
}
@media screen and (min-width: 960px){
.carousel-container .items.placeholder-slider {
width: 80%;
}
}
@media screen and (min-width: 769px), print{
.carousel-container .items.placeholder-slider {
max-width: none;
}
}
@media screen and (min-width: 769px), print{
.carousel-container .items .slider-item {
display: inline-block;
-webkit-box-sizing: border-box;
box-sizing: border-box;
height: 100%;
width: 100%;
}
}
@media screen and (min-width: 960px){
.carousel-container .items.placeholder-slider .slider-item {
-webkit-transform: scale(0.92);
transform: scale(0.92);
}
}
@media screen and (min-width: 960px){
.carousel-container .items.placeholder-slider .slider-item.active {
-webkit-transform: scale(1.05);
transform: scale(1.05);
}
}
img {
display: table;
max-width: 100%;
object-fit: cover;
margin: 0 auto;
}
.carousel-container__slide__content {
width: 100%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: pointer;
}
@media screen and (min-width: 769px), print{
.carousel-container__slide__content {
border-radius: 16px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.js"></script>
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>vue.js carousel</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="app">
<section class="slide-placeholder">
<div class="slide-placeholder__carousel-container">
<div class="carousel-container__background" :style="'background-image: url(' + carousels[show].img + ')'"></div>
<div class="custom__container">
<div class="carousel-container" ref="carousel" data-auto="true" data-delay="1500000" @mouseenter.stop="toggleTimer = false" @mouseleave.stop="toggleTimer = true" @touchstart.stop="touchStart" @touchmove.stop="touchMove" :style="'min-height:' + minHeight ">
<keep-alive>
<transition :name="carouselName">
<div class="items placeholder-slider" v-for="(s, i) in carousels" v-if="show == i" :key="i">
<div class="slider-item active">
<div class="carousel-container__slide">
<a :href="s.href">
<img :src="s.img" class="carousel-container__slide__content">
</a>
</div>
</div>
</div>
</transition>
</keep-alive>
<a class="button-prev" href="#" @click.prevent="toPrev" style="color: white; text-decoration:none; font-size:50px">
<
</a>
<a class="button-next" href="#" @click.prevent="toNext" style="color: white; text-decoration:none; font-size:50px">
>
</a>
<div class="dot-group"><a v-for="(l, i) in len" href="#" :class="{ 'active': show == i }" @click.prevent="show = i"></a></div>
</div>
</div>
</div>
</section>
</div>
</body>
</html>