<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3D Slider</title>
<style>
body {
background: #222;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
margin: 0;
}
#wrap {
display: grid;
align-items: center;
justify-items: center;
width: 100%;
}
.slider3d {
grid-row: 1/2;
grid-column: 1/2;
width: 20%;
height: auto;
display: grid;
transform-style: preserve-3d;
}
.slide-trans {
transition: transform 0.3s;
transition-timing-function: linear;
}
.slider3d>figure {
grid-row: 1/2;
grid-column: 1/2;
margin: 0;
padding: 0;
transform-style: preserve-3d;
}
.slider3d figure img {
width: 100%;
height: auto;
object-fit: cover;
border: 7px solid #f2f2f2;
}
#ovl {
grid-row: 1/2;
grid-column: 1/2;
width: 500px;
height: 400px;
}
</style>
</head>
<body>
<div id="wrap">
<div class="slider3d">
</div>
<div id="ovl"></div>
</div>
<script>
const
animObj = new Animation(null, document.timeline),
slider3D = document.querySelector('.slider3d');
let boxOvl, rotateKeyframes, rotateKeyframesReverse, speed = 1;
function dynStyle() {
boxOvl = document.getElementById('ovl').getBoundingClientRect();
const
wSlider3D = slider3D.clientWidth,
perspective = (wSlider3D * 3) + 'px',
translateZ = (wSlider3D * 1.5) + 'px';
slider3D.classList.add("slide-trans");
const
innerWrappers = slider3D.querySelectorAll('figure');
for (i = 0; i < innerWrappers.length; i++) {
innerWrappers[i].style.transform = "rotateY(" + (i * (360 / imgs.length)) + "deg) translateZ(" + translateZ + ")";
}
rotateKeyframes = new KeyframeEffect(
slider3D,
[
{ transform: 'perspective(' + perspective + ') rotateY(0deg)' },
{ transform: 'perspective(' + perspective + ') rotateY(360deg)' }
],
{ duration: duration, iterations: Infinity }
);
rotateKeyframesReverse = new KeyframeEffect(
slider3D,
[
{ transform: 'perspective(' + perspective + ') rotateY(0deg)' },
{ transform: 'perspective(' + perspective + ') rotateY(-360deg)' }
],
{ duration: duration, iterations: Infinity }
);
if (speed > 0) {
animObj.effect = rotateKeyframes;
} else {
animObj.effect = rotateKeyframesReverse;
}
}
const
duration = 10000,
imgs = ["dia0.jpg", "dia1.jpg", "dia2.jpg", "dia3.jpg", "dia4.jpg", "dia5.jpg"],
folder = "images";
for (i = 0; i < imgs.length; i++) {
const innerWrapper = document.createElement("figure");
innerWrapper.innerHTML = "<img src='" + folder + "/" + imgs[i] + "'\>";
slider3D.appendChild(innerWrapper);
}
dynStyle();
animObj.playbackRate = 0;
animObj.play();
document.addEventListener("mousemove", (event) => {
const
posX = event.clientX,
posRel = posX - (boxOvl.left + boxOvl.width / 2),
speedNew = posRel / boxOvl.width;
console.log(speedNew)
if (Math.sign(speedNew) != Math.sign(speed) || speed == null) {
animObj.currentTime = duration - animObj.currentTime % duration;
if (Math.sign(speedNew) > 0) {
animObj.effect = rotateKeyframes;
console.log('forward')
} else {
animObj.effect = rotateKeyframesReverse;
console.log('reverse')
}
}
animObj.playbackRate = Math.abs(speedNew);
speed = speedNew;
});
window.addEventListener('resize', dynStyle);
</script>
</body>
</html>