-
horizontal Slidert
-
vertical Slider
Slider auf JavaScript Basis habe ich schon einige geschrieben, nun aber versuche ich es mit einem anderen Ansatz, für das Sliden möchte ich das über CSS gestaltete Scrollen nutzen, dadurch ist die Umsetzung der Touch- und Wheel-Events nicht erforderlich, da es im Standard schon funktioniert.
Als Methoden zur Animierung sollen dann zusätzlich zum Wischen und Mousewheel/Mouspad (2-Finger), noch Pfeile (vorwärts/rückwärts), Bubbes (Punkte zur Steuerung und Anzeige aktiver Slide) oder Thumbnails (Bilder zur Steuerung und Anzeige aktiver Slide) und eine Autoplay Funktion (optional mit Play & Pause Button).
Das Sliden soll in horzontaler aber auch vertikaler Richtung funktionieren.
Es ist klar das hierbei alte Browser nicht so einfach berücksichtigt werden können, aber schauen wir mal was geht.
HTML:
<!DOCTYPE html >
<html lang="de">
<head>
<meta charset="utf-8" />
<title>Slider</title>
<link rel="stylesheet" href="../tabsheet.css" />
</head>
<body>
<ul class="tabsheets">
<li class="active">
<h4 class="sheet-header">horizontal Slidert</h4>
<div class="flex-slider" data-options="thumbs arrows autoplay play&pause">
<ul>
<li><img src="IMG_6867.jpg" /></li>
<li><img src="IMG_6868.jpg" /></li>
<li><img src="IMG_6869.jpg" /></li>
<li><img src="IMG_6870.jpg" /></li>
<li><img src="IMG_6871.jpg" /></li>
<li><img src="IMG_6872.jpg" /></li>
</ul>
</div>
</li>
<li>
<h4 class="sheet-header">vertical Slider</h4>
<div class="flex-slider vertical" data-options="thumbs arrows autoplay">
<ul>
<li><img src="IMG_6867.jpg" /></li>
<li><img src="IMG_6868.jpg" /></li>
<li><img src="IMG_6869.jpg" /></li>
<li><img src="IMG_6870.jpg" /></li>
<li><img src="IMG_6871.jpg" /></li>
<li><img src="IMG_6872.jpg" /></li>
</ul>
</div>
</li>
</ul>
<script src="../tabsheet.js"></script>
<script src="flex-slider.js"></script>
</body>
</html>
JavaScript:
// coding: utf-8
/** Created by: Udo Schmal | https://www.gocher.me/ */
(function() {
'use strict';
// scroll into parent view
Element.prototype.scrollIntoParentView = function () {
this.parentNode.scrollTo({top: this.offsetTop, left: this.offsetLeft, behavior: 'smooth'});
};
function Slider(el) {
var slider = el; // slider div
var slides = el.querySelector('ul'); // slides ul list
if (!slides.classList.contains('slides')) {
slides.classList.add('slides');
}
var items = slides.children; // slides li items
var controls = null; // bubbles/thumbs ul list
var controlItems = []; // bubbles/thumbs li items
var prev = null; // previous div button
var next = null; // next div button
var play = null; // play & pause div button
var active = 0; // active slide position counter
// load stylesheet
if (!document.getElementById('flex-slider.css')) {
var style = document.createElement("link");
style.type = 'text/css';
style.href = '/code/flex-slider/flex-slider.css';
style.id = 'flex-slider.css';
style.rel = 'stylesheet';
document.head.appendChild(style);
}
// get settings from dom
var direction = el.classList.contains('vertical') ? 'vertical' : 'horizontal';
if ((direction == 'horizontal') && !el.classList.contains('horizontal')) {
el.classList.add('horizontal');
}
var thumbs = false, bubbles = false, autoplay = false, arrows = false, playpause = false;
if (el.dataset.options) {
thumbs = el.dataset.options.indexOf('thumbs') !== -1;
bubbles = el.dataset.options.indexOf('bubbles') !== -1;
autoplay = el.dataset.options.indexOf('autoplay') !== -1;
arrows = el.dataset.options.indexOf('arrows') !== -1;
playpause = el.dataset.options.indexOf('play&pause') !== -1;
}
// slide & snap
function startScroll() {
for (let i = 0; i < items.length; i++) {
items[i].classList.remove('active');
if (controls) {
controlItems[i].classList.remove('active');
}
}
}
function stopScroll() {
scrollTimer = null;
for (let i = 0; i < items.length; i++) {
if ((Math.abs(slides.scrollTop - items[i].offsetTop) < 5) &&
(Math.abs(slides.scrollLeft - items[i].offsetLeft) < 5)) {
if (controls) {
controlItems[i].classList.add('active');
}
items[i].classList.add('active');
active = i;
}
}
if (prev) {
if (active == 0) {
prev.classList.add('hidden');
} else {
prev.classList.remove('hidden');
}
}
if (next) {
if (active == items.length-1) {
next.classList.add('hidden');
} else {
next.classList.remove('hidden');
}
}
}
var scrollTimer;
function sliderScroll(event) {
if (scrollTimer) {
clearTimeout(scrollTimer);
} else {
startScroll();
}
scrollTimer = setTimeout(stopScroll, 20);
}
slides.addEventListener('scroll', sliderScroll);
// auto slide
var slideshow = null;
var restartTimer;
function startSlideshow () {
if (restartTimer) {
clearTimeout(restartTimer);
}
if (!slideshow) {
slideshow = window.setInterval(function () {
if (active+1 < items.length) {
items[++active].scrollIntoParentView();
} else {
items[0].scrollIntoParentView();
}
}, 3000);
}
}
function stopSlideShow () {
if (slideshow) {
window.clearInterval(slideshow);
slideshow = null;
}
}
function pauseSlideshow () {
if (slideshow) {
window.clearInterval(slideshow);
slideshow = null;
restartTimer = setTimeout(startSlideshow, 5000);
};
}
function toggleSlideshow () {
if (play.classList.contains('play')) {
startSlideshow();
play.classList.remove('play');
play.classList.add('pause');
} else {
stopSlideShow();
play.classList.remove('pause');
play.classList.add('play');
}
}
if (autoplay) {
startSlideshow();
// mousepad, wheel scroll
el.addEventListener('wheel', pauseSlideshow, true);
// touch screen
el.addEventListener('touch', pauseSlideshow, true);
el.addEventListener('touchstart', pauseSlideshow, true);
el.addEventListener('touchend', pauseSlideshow, true);
el.addEventListener('touchmove', pauseSlideshow, true);
el.addEventListener('touchcancel', pauseSlideshow, true);
}
// play & pause button
if (playpause) {
play = document.createElement('div');
play.className = autoplay ? 'pause' : 'play';
play.addEventListener('click', toggleSlideshow);
el.appendChild(play);
}
// control bubbles
if (bubbles || thumbs) {
controls = document.createElement('ul');
controls.classList.add('controls');
controls.classList.add(thumbs ? 'thumbs' : 'bubbles');
el.appendChild(controls);
function controlClick(event) {
if (autoplay) {
pauseSlideshow();
}
this.slide.scrollIntoParentView();
}
for(let i = 0; i < items.length; i++) {
let li = document.createElement('li');
li.slide = items[i];
if (thumbs) {
let img = items[i].querySelector('img');
if (img) {
if (img.src) {
li.style.backgroundImage = 'url("' + img.src + '")';
} else if (img.dataset.src) {
li.style.backgroundImage = 'url("' + img.dataset.src + '")';
}
}
}
li.addEventListener('click', controlClick);
controls.appendChild(li);
}
controlItems = controls.children;
controlItems[active].classList.add('active');
}
// previous & next button
if (arrows) {
prev = document.createElement('div');
prev.className = 'prev';
function prevClick() {
if (autoplay) {
pauseSlideshow();
}
items[--active].scrollIntoParentView();
}
prev.addEventListener('click', prevClick);
el.appendChild(prev);
next = document.createElement('div');
next.className = 'next';
function nextClick() {
if (autoplay) {
pauseSlideshow();
}
items[++active].scrollIntoParentView();
}
next.addEventListener('click', nextClick);
el.appendChild(next);
}
}
var els = document.querySelectorAll('.flex-slider'), cnt = els.length, i;
for (i=0; i < cnt; i++) {
new Slider(els[i]);
}
})();
StyleSheet:
.flex-slider {
position: relative;
overflow: hidden;
width: 100%;
height: 0;
min-height: 1px;
padding-top: 44%;
}
.flex-slider > .slides {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0;
padding: 0;
list-style-type: none;
scroll-behavior: smooth;
/*overflow-scrolling: auto;*/
/* hide IE scrollbar */
-ms-overflow-style: none;
}
/* hide WebKit scrollbar */
.flex-slider > .slides::-webkit-scrollbar {
display: none;
}
.flex-slider.horizontal > .slides {
bottom: -12px; /* scrollbar fix */
display: flex;
scroll-snap-type: x mandatory;
overflow-x: scroll;
overflow-y: hidden;
}
.flex-slider.vertical > .slides {
right: -12px; /* scrollbar fix */
scroll-snap-type: y mandatory;
overflow-y: scroll;
overflow-x: hidden;
}
.flex-slider .slides > li {
position: relative;
margin: 0;
padding: 0;
scroll-snap-align: start;
}
.flex-slider.horizontal .slides > li {
width: 100%;
height: auto;
display: inline-block;
flex-shrink: 0;
}
.flex-slider.vertical .slides > li {
height: 100%;
width: auto;
}
.flex-slider > .slides > li > img {
width: 100%;
height: auto;
}
.flex-slider > .controls {
right: 0;
}
.flex-slider.horizontal > .controls {
position: absolute;
left: 0;
bottom: 15px;
text-align: center;
}
.flex-slider.vertical > .controls {
position: absolute;
top: 50%;
right: 25px;
transform: translate(0, -50%);
display: block;
}
.flex-slider.vertical > .controls::after {
display: table;
content: '';
clear: both;
}
.flex-slider.horizontal > .controls.thumbs {
height: 10%;
}
.flex-slider.vertical > .controls.thumbs {
width: 10%;
}
.flex-slider > .controls > li {
display: inline-block;
outline: none;
background-color: #fff;
opacity: 0.8;
cursor: pointer;
}
.flex-slider.horizontal > .controls > li {
display: inline-block;
margin: 0 5px;
}
.flex-slider.vertical > .controls > li {
display: block;
margin: 5px 0;
}
.flex-slider > .controls.bubbles > li {
border: 1px solid #000;
transition: border 500ms ease-out;
width: 0.85em;
height: 0.85em;
border-radius: 50%;
}
.flex-slider > .controls.thumbs > li {
border: 2px solid #000;
transition: border 500ms ease-out;
}
.flex-slider > .controls.bubbles > li.active {
background-color: #000;
}
.flex-slider > .controls.thumbs > li.active {
border-color: #fff;
}
.flex-slider > .controls.thumbs > li {
position: relative;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
.flex-slider.horizontal > .controls.thumbs > li {
width: 10%;
height: 100%;
}
.flex-slider.vertical > .controls.thumbs > li {
padding-top: 44%;
width: 100%;
}
.flex-slider > .prev, .flex-slider > .next, .flex-slider > .play, .flex-slider > .pause {
cursor: pointer;
position: absolute;
}
.flex-slider.horizontal > .prev, .flex-slider.horizontal > .next {
top: 50%;
transform: translate(0, -50%);
}
.flex-slider.vertical > .prev, .flex-slider.vertical > .next {
left: 50%;
transform: translate(-50%, 0);
}
.flex-slider.horizontal > .prev {
left: 15px;
}
.flex-slider.horizontal > .next {
right: 15px;
}
.flex-slider.vertical > .prev {
top: 15px;
}
.flex-slider.vertical > .next {
bottom: 15px;
}
.flex-slider > .prev.hidden, .flex-slider > .next.hidden {
display: none;
}
.flex-slider > .prev::after, .flex-slider > .next::after, .flex-slider > .play::after, .flex-slider > .pause::after {
display: inline-block;
color: #fff;
font-size: 2em;
}
.flex-slider.horizontal > .prev::after {
content: '\140a';
}
.flex-slider.horizontal > .next::after {
content: '\1405';
}
.flex-slider.vertical > .prev::after {
content: '\1403';
}
.flex-slider.vertical > .next::after {
content: '\1401';
}
.flex-slider > .play, .flex-slider > .pause {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.flex-slider:hover > .play::after {
content: '\23EF';
}
.flex-slider:hover > .pause::after {
content: '\23f8';
}