What I've figured out is that it seems to run the slide to function twice upon swipe, and every once in a while I am able to get the right behavior, but it's so unpredictable. It seems to only work when I swipe just barely. I've tried changing the minimum swipe distance required, no dice. Please help!
const slider = document.querySelector('.slider');
const sliderContainer = document.querySelector('.sliderContainer');
const items = document.querySelectorAll('.item');
const rowGap = (window.innerWidth / 2); // Adjust this value based on your desired row gap
let currentIndex = 0;
let index = 0;
let touchStartX = 0;
let touchStartY = 0;
// Calculate the total width of all items, including the row gap
const totalItemsWidth = Array.from(items).reduce((total, item) => {
const itemStyle = getComputedStyle(item);
const itemWidth = item.offsetWidth + parseFloat(itemStyle.marginLeft) + parseFloat(itemStyle.marginRight);
return total + itemWidth + rowGap;
}, 0);
// Set the width of the slider container to accommodate all items
sliderContainer.style.width = `${totalItemsWidth}px`;
function slideTo(index, swipe) {
let translation;
if (currentIndex == 2 && swipe != true) {
console.log(currentIndex + index);
index = 0;
}
if (index < 0 || index >= items.length) {
return;
}
translation = index * (items[0].offsetWidth + rowGap);
sliderContainer.style.transform = `translateX(-${translation}px)`;
currentIndex = index;
return;
}
function slideNext(swipe) {
slideTo(currentIndex + 1, swipe);
}
function slidePrev(swipe) {
slideTo(currentIndex - 1, swipe);
}
setInterval(slideNext, 8500); // Automatically slide every 4.5 seconds
slider.addEventListener('touchstart', handleTouchStart);
slider.addEventListener('touchmove', handleTouchMove);
slider.addEventListener('touchend', handleTouchEnd);
function handleTouchStart(event) {
touchStartX = event.touches[0].clientX;
}
function handleTouchMove(event) {
event.preventDefault(); // Prevent default scrolling behavior
const touchX = event.touches[0].clientX;
const touchDiff = touchX - touchStartX;
console.log("hi")
if (touchDiff > 50) {
slidePrev(true);
} else if (touchDiff < -50) {
slideNext(true);
}
}
function handleTouchEnd() {
touchStartX = 0;
}
.slider {
margin: auto;
display: flex;
width: fit-content;
overflow: hidden;
gap: 50vw;
position: relative;
left: 1%;
}
.sliderContainer {
display: flex;
transition: transform 0.3s ease;
padding-bottom: 3vh;
position: relative;
}
.sliderWrapper {
height: auto;
width: 99.5%;
overflow: hidden;
background-color: white;
border: 1px solid #E28C4A;
}
.sliderWrapper h1 {
font-size: 11vmin;
margin: 15px 0 15px 0;
color: #9D000D;
}
.item {
flex: 0 0 300px;
display: flex;
flex-direction: column;
}
.item img {
width: 97%;
border-radius: 15px;
}
.item > button {
width: 95%;
}
.item h2 {
min-width: 340px;
font-size: 30px;
margin: 7px 0 15px 0;
}
<div class="sliderWrapper">
<h1>What's Popular</h1>
<div class="sliderContainer">
<div class="slider">
<div id="butterPecan" class="item">
<div class="textWrapper">
<img src="Images/Butter-Pecan-Mobile.webp">
<h2>Butter Pecan</h2>
</div>
<button>Order ahead</button>
</div>
<div class="item">
<div class="textWrapper">
<img id="mintChocolate" src="Images/Mint-Chocolate-Chip-Mobile.webp">
<h2>Mint Chocolate Chip</h2>
</div>
<button>Order ahead</button>
</div>
<div class="item">
<div class="textWrapper">
<img id="peanutButter" src="Images/Peanut-Butter-Chippy-Mobile.webp">
<h2>Peanut Butter Chippy</h2>
</div>
<button>Order ahead</button>
</div>
</div>
</div>
</div>
You've set up your
handleTouchMovefunction to fire every time the user moves their finger. Inside the function, you measure the displacement with respect to where the gesture started. If the displacement exceeds 50 pixels, you trigger a slide change.Once the displacement has reached 50, every subsequent move triggers a change, which explains the behavior you observed:
Depending on what you believe is proper UX, you could either:
To reset the displacement, set
touchStartXtotouchX. You don't need thetouchendlistener.To prevent multiple slides, introduce a new variable to keep track of whether the user has swiped or not: