Je pense que c'est ce que vous voulez: https://codepen.io/mukyuu/pen/GRgPYqG .
Il a presque rempli vos conditions, sauf qu'il n'utilise pas Swiper 5 et Snap.
- Il tourne avec la direction du balayage.
- Avec un balayage rapide, il devrait faire défiler de nombreuses diapositives avec élan (comme le fait Swiper).
Puis, lorsque la roue cesse de tourner, elle s'enclenche sur une glissière (comme le fait Swiper).
- En
ontouch
fonction il y a un rappel.
HTML:
<div class="carousel" id="wrapper">
<figure>
<img src="https://source.unsplash.com/7mUXaBBrhoA/800x533" alt="">
<img src="https://source.unsplash.com/bjhrzvzZeq4/800x533" alt="">
<img src="https://source.unsplash.com/EbuaKnSm8Zw/800x533" alt="">
<img src="https://source.unsplash.com/kG38b7CFzTY/800x533" alt="">
<img src="https://source.unsplash.com/nvzvOPQW0gc/800x533" alt="">
<img src="https://source.unsplash.com/mCg0ZgD7BgU/800x533" alt="">
<img src="https://source.unsplash.com/1FWICvPQdkY/800x533" alt="">
<img src="https://source.unsplash.com/VkwRmha1_tI/800x533" alt="">
</figure>
</div>
S (CSS):
body {
margin: 0;
font-family: 'Roboto';
font-size: 16px;
display: flex;
flex-direction: column;
height: 100vh;
justify-content: center;
}
// Carousel configuration parameters
$n: 8;
$item-width: 400px;
$item-separation: 80px;
$viewer-distance: 500px;
// Derived variables
$theta: 2 * 3.141592653589793 / $n;
$apothem: 482.842712474619px;
.carousel {
padding: 20px;
perspective: $viewer-distance;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
> * {
flex: 0 0 auto;
}
figure {
cursor: grab;
margin: 0;
width: $item-width;
transform-style: preserve-3d;
transition: transform 0.5s;
transform-origin: 50% 50% (-$apothem);
img {
width: 100%;
box-sizing: border-box;
padding: 0 $item-separation / 2;
opacity: 0.9;
&:not(:first-of-type) {
position: absolute;
left: 0;
top: 0;
transform-origin: 50% 50% (-$apothem);
}
@for $i from 2 through $n {
&:nth-child(#{$i}) {
transform: rotateY(#{($i - 1) * $theta}rad);
}
}
}
}
nav {
display: flex;
justify-content: center;
margin: 20px 0 0;
button {
flex: 0 0 auto;
margin: 0 5px;
cursor: pointer;
color: #333;
background: none;
border: 1px solid;
letter-spacing: 1px;
padding: 5px 10px;
}
}
}
JS:
var
carousel = document.querySelector('.carousel'),
figure = carousel.querySelector('figure'),
nav = carousel.querySelector('nav'),
numImages = figure.childElementCount,
theta = 2 * Math.PI / numImages,
currImage = 0
;
// add touch detect:
function ontouch(el, callback){
// Modified from http://www.javascriptkit.com/javatutors/touchevents3.shtml
var touchsurface = el,
dir,
swipeType,
startX,
startY,
distX,
distY,
threshold = 150, //required min distance traveled to be considered swipe
restraint = 100, // maximum distance allowed at the same time in perpendicular direction
allowedTime = 500, // maximum time allowed to travel that distance
elapsedTime,
startTime,
handletouch = callback || function(evt, dir, phase, swipetype, distance){}
touchsurface.addEventListener('touchstart', function(e){
var touchobj = e.changedTouches[0]
dir = 'none'
swipeType = 'none'
dist = 0
startX = touchobj.pageX
startY = touchobj.pageY
startTime = new Date().getTime() // record time when finger first makes contact with surface
handletouch(e, 'none', 'start', swipeType, 0) // fire callback function with params dir="none", phase="start", swipetype="none" etc
e.preventDefault()
}, false)
touchsurface.addEventListener('touchmove', function(e){
var touchobj = e.changedTouches[0]
distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface
distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface
if (Math.abs(distX) > Math.abs(distY)){ // if distance traveled horizontally is greater than vertically, consider this a horizontal movement
dir = (distX < 0)? 'left' : 'right'
handletouch(e, dir, 'move', swipeType, distX) // fire callback function with params dir="left|right", phase="move", swipetype="none" etc
}
else{ // else consider this a vertical movement
dir = (distY < 0)? 'up' : 'down'
handletouch(e, dir, 'move', swipeType, distY) // fire callback function with params dir="up|down", phase="move", swipetype="none" etc
}
e.preventDefault() // prevent scrolling when inside DIV
}, false)
touchsurface.addEventListener('touchend', function(e){
var touchobj = e.changedTouches[0]
elapsedTime = new Date().getTime() - startTime // get time elapsed
if (elapsedTime <= allowedTime){ // first condition for awipe met
if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met
swipeType = dir // set swipeType to either "left" or "right"
}
else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met
swipeType = dir // set swipeType to either "top" or "down"
}
}
// Fire callback function with params dir="left|right|up|down", phase="end", swipetype=dir etc:
handletouch(e, dir, 'end', swipeType, (dir =='left' || dir =='right')? distX : distY)
e.preventDefault()
}, false)
}
function DoSomething(dir, distance) {
//modifiy this function for wheel rotation (prev/next) images
var momentum = 100; // modify this value for how much momentum expected to switch to next/prev images
switch (dir){
case 'left':
case 'right':
currImage+= Math.round(distance/momentum);
break;
}
figure.style.transform = `rotateY(${currImage * -theta}rad)`;
}
document.getElementById('wrapper').ondragstart = function() { return false; }; // prevent image dragged on mouse drag
window.addEventListener('load', function() {
var dir, phase, el = document.getElementById('wrapper'),
position = {
X: 0,
Y: 0
};
el.onmousedown = function(down) {
position.X = down.clientX;
position.Y = down.clientY;
};
el.onmouseup = function(up) {
distX = up.clientX - position.X; // get horizontal dist traveled by finger while in contact with surface
distY = position.Y - up.clientY; // get vertical dist traveled by finger while in contact with surface
if (Math.abs(distX) > Math.abs(distY)) { // if distance traveled horizontally is greater than vertically, consider this a horizontal movement
dir = (distX < 0) ? 'left' : 'right';
distance = distX;
} else { // else consider this a vertical movement
dir = (distY < 0) ? 'down' : 'up';
distance = distY;
}
dir = (distance == 0) ? 'none' : dir;
DoSomething(dir, distance); // simulate touch from mouse control
};
ontouch(el, function(evt, dir, phase, swipetype, distance){
// evt: contains original Event object
// dir: contains "none", "left", "right", "top", or "down"
// phase: contains "start", "move", or "end"
// swipetype: contains "none", "left", "right", "top", or "down"
// distance: distance traveled either horizontally or vertically, depending on dir value
if ( phase == 'end' && (dir =='left' || dir == 'right') ) // on succesful swipe
DoSomething(dir, distance);
})
}, false)
Testé dans les navigateurs Android 9 et Windows 10.