I'm trying to program a webpage animation where a user can have the choice of clicking & dragging or simply scrolling using the mouse wheel to view a vertical stack of images. Click & drag works fine, however the scrolling input doesn't work as desired. When I attempt to scroll though the pictures, input doesn't seem to register. When I click & drag first, and then scroll, the scroll feature works.
Html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>CoolEffect</title>
</head>
<body>
<div id = "image-track" data-mouse-down-at = "0" data-prev-percentage = "0">
<img class="image" src="assets/photo-1542051841857-5f90071e7989.jpeg" draggable="false">
<img class="image" src="assets/photo-1533050487297-09b450131914.jpeg" draggable="false">
<img class="image" src="assets/photo-1564284369929-026ba231f89b.jpeg" draggable="false">
<img class="image" src="assets/photo-1528360983277-13d401cdc186.jpeg" draggable="false">
<img class="image" src="assets/photo-1492571350019-22de08371fd3.jpeg" draggable="false">
<img class="image" src="assets/photo-1532884928231-ef40895eb654.jpeg" draggable="false">
<img class="image" src="assets/photo-1540959733332-eab4deabeeaf.jpeg" draggable="false">
</div>
<script src="script.js"></script>
</body>
</html>
CSS
body{
height: 100vh;
width: 100vw;
background-color: black;
margin: 0rem;
overflow: hidden;
}
#image-track > .image {
width: 150vmin;
height: 50vmin;
object-fit: cover;
object-position: 100% 0%;
}
#image-track {
display: flex;
flex-direction: column;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
JavaScript
const track = document.getElementById("image-track");
window.onmousedown = e => {
track.dataset.mouseDownAt = e.clientY;
}
window.onmouseup = () => {
track.dataset.mouseDownAt = "0";
track.dataset.prevPercentage = track.dataset.percentage;
}
window.onmousemove = e => {
if(track.dataset.mouseDownAt === "0") return;
const mouseDelta = parseFloat(track.dataset.mouseDownAt) - e.clientY,
maxDelta = window.innerHeight;
let percentage = (mouseDelta / maxDelta) * -100,
nextPercentage = parseFloat(track.dataset.prevPercentage) + percentage;
nextPercentage = Math.max(-100, Math.min(0, nextPercentage));
track.dataset.percentage = nextPercentage;
track.animate(
{transform :`translate(-50%, ${nextPercentage}%)`},
{duration: 1200, fill: "forwards"});
for(const image of track.getElementsByClassName("image")){
image.animate(
{objectPosition : `50% ${nextPercentage + 100}%`},
{duration: 1200, fill: "forwards"});
}
}
window.addEventListener("wheel", e => {
e.preventDefault();
const deltaY = e.deltaY;
const maxDelta = window.innerHeight;
let percentage = (deltaY / maxDelta) * -100,
nextPercentage = parseFloat(track.dataset.percentage) + percentage;
nextPercentage = Math.max(-100, Math.min(0, nextPercentage));
track.dataset.percentage = nextPercentage;
track.animate(
{ transform: `translate(-50%, ${nextPercentage}%)` },
{ duration: 1200, fill: "forwards" }
);
for (const image of track.getElementsByClassName("image")) {
image.animate(
{ objectPosition: `50% ${nextPercentage + 100}%` },
{ duration: 1200, fill: "forwards" }
);
}
scrollStartY = e.pageY;
});
What I expected to happen was regardless of previous input, the user can scroll or click & drag to view the images. Without clicking and dragging first, the user is unable to do so. I first thought the issue lied in the default scrolling behaviour of the page, so I added to e.preventDefault() to negate this. This however wasn't the issue. Any suggestions as to what could be causing the issue?
You are only modifying the track.dataset.percentage value when scrolling, but you're not updating track.dataset.prevPercentage to reflect the current state.
let scrollStartY = 0;
window.addEventListener("wheel", e => {
e.preventDefault();
const deltaY = e.deltaY;
const maxDelta = window.innerHeight;
let percentage = (deltaY / maxDelta) * -100,
nextPercentage = parseFloat(track.dataset.percentage) + percentage;
nextPercentage = Math.max(-100, Math.min(0, nextPercentage));
track.dataset.prevPercentage = track.dataset.percentage; // Update prevPercentage
track.dataset.percentage = nextPercentage;
track.animate(
{ transform: `translate(-50%, ${nextPercentage}%)` },
{ duration: 1200, fill: "forwards" }
);
for (const image of track.getElementsByClassName("image")) {
image.animate(
{ objectPosition: `50% ${nextPercentage + 100}%` },
{ duration: 1200, fill: "forwards" }
);
}
});