Ich denke, das ist was Sie wollen: https://codepen.io/mukyuu/pen/GRgPYqG .
Es hat Ihre Bedingungen fast erfüllt, außer dass Swiper 5 und Snap nicht verwendet werden.
- Es dreht sich mit der Richtung des Wischens.
- Mit einem schnellen Wischen sollten viele Folien mit Schwung gescrollt werden (wie es Swiper tut).
Wenn sich das Rad dann nicht mehr dreht, rastet es auf einem Schlitten ein (wie es Swiper tut).
- In der
ontouch
Funktion gibt es einen Rückruf.
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)
Getestet in Android 9 und Windows 10 Browsern.