Der folgende Beitrag ist ein Gastbeitrag von Kevin Foley. Kevin ist Entwickler bei Squarespace und beschäftigt sich unter anderem mit deren Entwicklerplattform. Er hat kürzlich an einer wischbaren Bildergalerie gearbeitet und sich bereit erklärt, einige seiner Arbeiten hier zu teilen!
Vor ein paar Wochen hat Chris ein Tutorial zum Erstellen eines Sliders mit gleitenden Hintergrundbildern veröffentlicht. Etwa zur gleichen Zeit arbeitete ich an einigen neuen wischbaren Galerien, also schlug Chris vor, dass ich ein Tutorial schreibe, wie man seinem Slider Wischunterstützung hinzufügt. Hier ist es!

Bei der Erstellung einer wischbaren Galerie gibt es zwei Techniken – soweit ich weiß –, aus denen man wählen kann. Man kann die Scroll-Position animieren oder das Element mit translate bewegen. Jede hat Vor- und Nachteile.
Translate verwenden
Das Verschieben des Sliders mit translate bietet den Vorteil von Hardwarebeschleunigung und Subpixel-Animation. Allerdings kann es beim ersten Touch-Ereignis zu einer kleinen Verzögerung – nur wenige zehn Millisekunden – kommen, bevor der Slider zu wischen beginnt. Dies ist nicht gut dokumentiert, ich habe es einfach in meiner Erfahrung bemerkt.
Overflow Scroll verwenden
Overflow scroll reagiert extrem schnell auf die anfängliche Berührung, da es nativ im Browser integriert ist. Sie müssen nicht auf den Event-Listener in JavaScript warten. Aber Sie verzichten auf die gesamte Glätte des Verschiebens von Elementen mit translate.
Für dieses Tutorial werden wir translate verwenden, da es meiner Meinung nach besser aussieht.
Das HTML
Das HTML in diesem Beispiel unterscheidet sich vom ursprünglichen Beispiel von Chris. Anstatt das Bild als Hintergrundbild festzulegen, werden wir es als Element festlegen. Das ermöglicht es uns, das Bild zu bewegen, um diesen coolen Schwenkeffekt mit translate zu erzielen, anstatt die Hintergrundposition zu animieren.
<div class="slider-wrap">
<div class="slider" id="slider">
<div class="holder">
<div class="slide-wrapper">
<div class="slide"><img class="slide-image" src="//farm8.staticflickr.com/7347/8731666710_34d07e709e_z.jpg" /></div>
74
</div>
<div class="slide-wrapper">
<div class="slide"><img class="slide-image" src="//farm8.staticflickr.com/7384/8730654121_05bca33388_z.jpg" /></div>
64
</div>
<div class="slide-wrapper">
<div class="slide"><img class="slide-image" src="//farm8.staticflickr.com/7382/8732044638_9337082fc6_z.jpg" /></div>
82
</div>
</div>
</div>
</div>
Das CSS
Zum größten Teil ist das CSS das gleiche wie bei Chris, daher werde ich nicht wiederholen, wie das Layout eingerichtet wird. Aber es gibt ein paar wichtige Unterschiede.
Anstatt einfach nur overflow scroll hinzuzufügen, müssen wir die Slides animieren. Dazu verwenden wir eine Klasse, um den Übergang einzurichten und ihn mit JavaScript hinzuzufügen, wenn wir ihn benötigen.
.animate { transition: transform 0.3s ease-out; }
IE 10 behandelt Touch-Ereignisse anders als mobile Webkit-Browser wie Chrome und Safari. Wir werden die Webkit-Touch-Ereignisse in JavaScript behandeln, aber in IE10 können wir diesen gesamten Slider (fast) mit nichts anderem als CSS erstellen.
.ms-touch.slider {
overflow-x: scroll;
overflow-y: hidden;
-ms-overflow-style: none;
/* Hides the scrollbar. */
-ms-scroll-chaining: none;
/* Prevents Metro from swiping to the next tab or app. */
-ms-scroll-snap-type: mandatory;
/* Forces a snap scroll behavior on your images. */
-ms-scroll-snap-points-x: snapInterval(0%, 100%);
/* Defines the y and x intervals to snap to when scrolling. */
}
Da diese Eigenschaften für die meisten Leute wahrscheinlich neu sind (sie waren es auch für mich), werde ich jede einzelne durchgehen und erklären, was sie tut.
-ms-scroll-chaining
Das Surface-Tablet wechselt die Browser-Tabs, wenn Sie über die Seite wischen, wodurch alle Wischereignisse für Entwickler nutzlos werden. Glücklicherweise ist es sehr einfach, dieses Verhalten zu überschreiben, indem Sie Scroll-Chaining für jedes gegebene Element auf none setzen.
-ms-scroll-snap-type
Wenn diese Eigenschaft auf mandatory gesetzt ist, überschreibt sie das Standard-Scrollverhalten des Browsers und zwingt ein scrollbares Element dazu, an einem bestimmten Intervall zu stoppen.
-ms-scroll-snap-points-x
Diese Eigenschaft legt die Intervalle fest, an denen das scrollbare Element einrastet. Sie akzeptiert zwei Zahlen: die erste Zahl ist der Startpunkt; die zweite ist das Snap-Intervall. In diesem Beispiel ist jeder Slide die volle Breite des übergeordneten Elements, was bedeutet, dass das Intervall 100% betragen sollte – d.h. das Element rastet bei 100%, 200%, 300% und so weiter ein.
-ms-overflow-style
Diese Eigenschaft ermöglicht es Ihnen, die Scrollleiste zu verbergen, wenn Sie sie auf none setzen.
Das JavaScript
Das Erste, was wir in JavaScript tun müssen, ist, zu erkennen, welche Art von Touch-Gerät wir verwenden. IE 10 verwendet Pointer-Ereignisse, während Webkit "touchstart", "touchmove" und "touchend" hat. Da der IE 10-Slider (fast) komplett in CSS ist, müssen wir das erkennen und dem Wrapper eine Klasse hinzufügen.
if (navigator.msMaxTouchPoints) {
$('#slider').addClass('ms-touch');
}
Ziemlich einfach. Wenn Sie den Slider bis zu diesem Zeitpunkt testen würden, wäre es eine funktionierende wischbare Diashow. Aber wir müssen immer noch den Schwenkeffekt auf die Bilder hinzufügen.
if (navigator.msMaxTouchPoints) {
$('#slider').addClass('ms-touch');
// Listed for the scroll event and move the image with translate.
$('#slider').on('scroll', function() {
$('.slide-image').css('transform','translate3d(-' + (100-$(this).scrollLeft()/6) + 'px,0,0)');
});
}
Und das war's für IE 10.
Nun zum Webkit-Weg. Dies wird alles in der else-Anweisung verpackt. Zuerst müssen wir nur ein paar Variablen definieren.
else {
var slider = {
// The elements.
el: {
slider: $("#slider"),
holder: $(".holder"),
imgSlide: $(".slide-image")
},
// The stuff that makes the slider work.
slideWidth: $('#slider').width(), // Calculate the slider width.
// Define these as global variables so we can use them across the entire script.
touchstartx: undefined,
touchmovex: undefined,
movex: undefined,
index: 0,
longTouch: undefined,
// etc
Dann müssen wir die Funktion initialisieren und die Ereignisse definieren.
// continued
init: function() {
this.bindUIEvents();
},
bindUIEvents: function() {
this.el.holder.on("touchstart", function(event) {
slider.start(event);
});
this.el.holder.on("touchmove", function(event) {
slider.move(event);
});
this.el.holder.on("touchend", function(event) {
slider.end(event);
});
},
Nun zu den spaßigen Dingen, die tatsächlich Dinge passieren lassen, wenn man den Slider wischt.
Touchstart
Auf dem iPhone (und den meisten anderen Touch-Slidern) springt der Slider zurück in seine ursprüngliche Position, wenn Sie ihn langsam, nur ein wenig, bewegen. Aber wenn Sie es schnell tun, wird er zum nächsten Slide weitergeschaltet. Diese schnelle Bewegung wird als "Flick" bezeichnet. Und es gibt keine native Möglichkeit, einen Flick zu erkennen, daher müssen wir einen kleinen Trick anwenden. Bei touchstart initialisieren wir eine setTimeout-Funktion und setzen eine Variable nach einer bestimmten Zeit.
this.longTouch = false;
setTimeout(function() {
// Since the root of setTimout is window we can’t reference this. That’s why this variable says window.slider in front of it.
window.slider.longTouch = true;
}, 250);
Wir müssen auch die ursprüngliche Position der Berührung ermitteln, um unsere Animation zu ermöglichen. Wenn Sie das noch nie gemacht haben, ist es etwas seltsam. JavaScript ermöglicht es Ihnen, Multitouch-Ereignisse zu definieren, sodass Sie dem Touch-Event eine Zahl übergeben können, die die Anzahl der Finger repräsentiert, auf die Sie achten. Für dieses Beispiel interessiere ich mich wirklich nur für einen Finger/Daumen, daher steht im folgenden Code-Beispiel die [0] dafür.
// Get the original touch position.
this.touchstartx = event.originalEvent.touches[0].pageX;
Bevor wir beginnen, den Slider zu bewegen, werde ich die animate-Klasse entfernen. Ich weiß, dass es im Moment keine animate-Klasse auf den Elementen gibt, aber wir brauchen sie für die nachfolgenden Slides. Wir fügen sie bei touchend wieder einem Element hinzu.
$('.animate').removeClass('animate');
Touchmove
Das touchmove-Ereignis verhält sich ähnlich wie Scroll-Ereignisse in JavaScript. Das heißt, wenn Sie etwas beim Scrollen tun, wird es mehrmals ausgeführt, während das Scrollen stattfindet. Wir werden also die touchmove-Position kontinuierlich abrufen, während der Finger/Daumen bewegt wird.
// Continuously return touch position.
this.touchmovex = event.originalEvent.touches[0].pageX;
Dann führen wir eine schnelle Berechnung durch, indem wir die touchstart-Position, die wir im letzten Ereignis erhalten haben, und die touchmove-Position verwenden, um herauszufinden, wie der Slide verschoben werden soll.
// Calculate distance to translate holder.
this.movex = this.index*this.slideWidth + (this.touchstartx - this.touchmovex);
Dann müssen wir das Bild schwenken, wie Chris es im Originalbeispiel getan hat. Wir verwenden dieselben magischen Zahlen wie er.
// Defines the speed the images should move at.
var panx = 100-this.movex/6;
Jetzt müssen wir eine Logik einbauen, um Randfälle zu behandeln. Wenn Sie sich auf dem ersten oder letzten Slide befinden, stoppt diese Logik das Schwenken des Bildes, wenn Sie in die falsche Richtung scrollen (d.h. in Richtung kein Inhalt). Dies ist vielleicht nicht die beste Methode, um dies zu handhaben, aber für mich funktioniert es im Moment.
if (this.movex < 600) { // Makes the holder stop moving when there is no more content.
this.el.holder.css('transform','translate3d(-' + this.movex + 'px,0,0)');
}
if (panx < 100) { // Corrects an edge-case problem where the background image moves without the container moving.
this.el.imgSlide.css('transform','translate3d(-' + panx + 'px,0,0)');
}
Touchend
Im touchend-Ereignis müssen wir herausfinden, wie weit der Benutzer den Slide bewegt hat, mit welcher Geschwindigkeit und ob diese Aktion zum nächsten Slide weitergeschaltet werden soll.
Zuerst müssen wir genau sehen, wie groß die zurückgelegte Distanz des Wischvorgangs war. Wir berechnen den Absolutwert der zurückgelegten Distanz, um zu sehen, ob der Benutzer gewischt hat.
// Calculate the distance swiped.
var absMove = Math.abs(this.index*this.slideWidth - this.movex);
Jetzt ermitteln wir, ob der Slider weitergeschaltet werden soll. Alle anderen Berechnungen in diesem Beispiel basieren auf der Index-Variable, also ist dies die eigentliche Logik hinter dem Skript. Es prüft, ob der Benutzer den Mindestabstand gewischt hat, um den Slider weiterzuschalten, oder ob die Bewegung ein Flick war. Und wenn eines dieser beiden Kriterien erfüllt ist, in welche Richtung ging der Wischvorgang.
// Calculate the index. All other calculations are based on the index.
if (absMove > this.slideWidth/2 || this.longTouch === false) {
if (this.movex > this.index*this.slideWidth && this.index < 2) {
this.index++;
} else if (this.movex < this.index*this.slideWidth && this.index > 0) {
this.index--;
}
}
Nun fügen wir die animate-Klasse hinzu und setzen die neue Translate-Position.
// Move and animate the elements.
this.el.holder.addClass('animate').css('transform', 'translate3d(-' + this.index*this.slideWidth + 'px,0,0)');
this.el.imgSlide.addClass('animate').css('transform', 'translate3d(-' + 100-this.index*50 + 'px,0,0)');
Fazit
Ja, Hurra für IE 10.
Aber im Ernst, das Erstellen von wischbaren Galerien ist eine ziemliche Plage, wenn man bedenkt, wie verbreitet dieses Idiom auf mobilen Betriebssystemen ist. Und das Endergebnis wird nicht so gut sein wie natives Wischen. Aber es wird nah dran sein.
Hier ist die vollständige Demo
Check out this Pen!
Am besten probieren Sie es hier auf Ihrem Touch-Gerät aus.
Ich habe es auf meinem Nexus 7 Tablet ausprobiert und der Slider funktioniert überhaupt nicht. Ich weiß, dass ich dicke Finger habe, aber etwas geht hier schief...
Ich habe das Beispiel tatsächlich nicht auf Android-Geräten getestet. Ich werde versuchen, ein Nexus 7 zu finden und herauszufinden, warum es nicht funktioniert.
Hier ist ein Bild, wie es auf einem Kindle Fire funktioniert: http://cl.ly/PdBK Es bleibt bei jeder Folienbewegung ein wenig "hängen", aber es wechselt die Folien und animiert den Übergang.
Ich versuche, mein Nexus 7 Tablet zum Laufen zu bringen. Aber es bootet nicht natürlich. omg ich hasse es. Aber ich werde in etwa 72 Stunden nachsehen, wenn es genug Saft hat, um zu starten.
Funktioniert auch großartig auf Chrome unter iOS – aber das ist kein großer Test, da es meistens wie Safari unter iOS ist (zumindest glaube ich das).
Meine beste Vermutung ist, dass ich 3D-Transformationen verwende, die nur in den neuesten Android-Browsern funktionieren. 2D-Transformationen wären besser unterstützt, wären aber nicht so flüssig.
http://caniuse.com/transforms2d
http://caniuse.com/transforms3d
Auf Nexus One mit dem neuesten Chrome-Browser funktioniert es nicht wie erwartet. Wenn ich darauf tippe, bewegt sich die Folie weiter, ich kann sie auch etwa 15% der nächsten Folie ziehen und dann darauf tippen, um diese Folie zu erhalten.
Kommt dem Funktionieren auf demselben Telefon mit Firefox näher, in diesem Fall wird nur ein Drittel des Bildes angezeigt, dann wenn Sie darauf drücken, erscheint das ganze Bild und Sie können es wunderschön wischen, nehmen Sie den Finger weg und zwei Drittel des Bildes verschwinden.
Dasselbe Telefon mit Dolphin-Browser funktioniert perfekt...
Funktioniert perfekt auf Chrome auf meinem iPad3 – schöner Slider!
Ich hoffe, Sie können es für Android debuggen
Bearbeiten – Nexus 4 … es war eine lange Woche. ;-O
Wie kann ich die Anzahl der angezeigten Bilder ändern? Ich habe 10 Bilder und es werden nur 3 angezeigt. Bitte helfen Sie!
Ich liebe es! Tolle Arbeit, Kevin, funktioniert super auf meinem iPhone.
Funktioniert nicht auf mobilem Chrome (Samsung Galaxy S4). Ich kann nur wenige Pixel nach links "scrollen" und das war's.
Ich habe dieses Problem auch auf meinem GS4 in Chrome.
Ja, ich habe genau dasselbe Problem mit Chrome auf meinem Galaxy S3.
Gleiches hier auf Chrome auf Samsung Galaxy SII.
Das tue ich auch. Es funktioniert überhaupt nicht im neuesten Chrome auf Note Android mit 4.1.
Ich habe dieses zufällige Plugin für so etwas gefunden und es hat für unsere Bedürfnisse sehr gut funktioniert und ist super flüssig: http://uraniumjs.com/widgets/carousel.html
Funktioniert kaum auf Google Nexus 4. Es sieht sehr gut aus, wenn die Slides tatsächlich gleiten.
funktioniert ziemlich gut auf dem iPhone. Muss es noch auf anderen Geräten/Browsern testen :-). Das einzige Problem mit diesem Slider ist, dass er nicht horizontal gesperrt ist. Dieses Problem habe ich bei den meisten Touch-freundlichen Slidern, die ich verwendet habe.
Toller Beitrag! Ich habe es auf einem Android-Tablet ausprobiert, und es hat – langsam – nur mit Flicks funktioniert. Andererseits hat es unter iOS großartig funktioniert.
Ich denke, Multitouch-Ereignisse unter Android sind einfach langsam: Ich habe diese Frage auf StackOverflow vor einiger Zeit gestellt und mich wegen der Leistung für native Lösungen entschieden.
Cooles Beispiel.
Mit Google Chrome auf einem Galaxy S3 (Android 4.1.2) war mein erster Instinkt, die Bilder zu wischen, was nicht funktioniert. Beim Tippen auf ein Bild ist der Schwenkeffekt großartig.
Der Grund, warum Sie einen "Ruckler" oder "Hänger" bemerken, wenn Sie anfangen, sich zu bewegen, ist, dass Sie von einem nicht-3D / nicht-beschleunigten DIV zu einem 3D / beschleunigten DIV wechseln. Dies zwingt den Browser, eine neue Bitmap zuzuweisen und das DIV darin neu zu rendern und dann zu animieren.
Um diesen Hänger zu vermeiden, setzen Sie transform: translate3D(0,0,0); BEVOR Sie touchstart auslösen. Dann wird die Kopie während des normalen Seitenrenderns durchgeführt. Voila, glatt. Kann auch translate3D(0,0,1px) verwenden, wenn Sie paranoid sind, dass Browser die 0,0,0-Version optimieren.
Guter Rat. Das werde ich versuchen. Danke, Matt.
Ich habe es geforkt und einiges ausprobiert, wie das Hinzufügen von translate3d (mit oder ohne die letzten 1px) in CSS, und das Hinzufügen in JS vor den Ereignissen, und andere Dinge, ohne Erfolg (auf meinem Nexus 7, das ich schließlich auseinandernehmen und den Akku wieder verbinden musste). Ich frage mich, ob Sie es forken und zum Laufen bringen könnten, Matt (oder jemand anderes).
Wie wäre es mit jquery?
Keine Absicht zu spammen, möchte nur die oben geposteten Beobachtungen erneut bestätigen. Ich habe unter Firefox und Chrome unter Android 4 getestet, und es ist auf die oben beschriebene Weise kaputt.
@Kevin Wenn Sie es für Android nicht zum Laufen bringen können, sollten Sie einen Haftungsausschluss-Abschnitt am Anfang des Beitrags hinzufügen, in dem Sie beschreiben, warum es unter Android fehlschlägt.
Codepen funktioniert auf meinem N4 nicht gut
dieser spezielle, um genau zu sein.
Auf meinem Windows Phone 7.8 (HTC HD7) wird nicht einmal das erste Bild vollständig angezeigt. Scrollen funktioniert überhaupt nicht… absolut nichts… sorry. Ich schätze, es liegt an diesem scheiß IE-Browser :D
Welche Version haben Sie? IE 9 oder IE 10?
WP 7.8 hat IE 9 installiert. Pointer Events wurden erst mit IE 10 eingeführt, was WP 8 auf Ihrem Telefon erfordert.
Dies funktioniert nicht auf meinem Nexus 4 mit Chrome und auf meinem Windows Phone 8 auf meinem HTC X8.
Getestet mit dem nativen Android-Browser und Chrome auf HTC One X, nicht gut, die rechte Seite zeigte einen Hauch eines anderen Bildes, etwa 2 mm erscheint, wenn ich berühre. Das ist alles.
Dasselbe auf Samsung Galaxy S 2 nativen Browser
Ich werde es forken und sehen, was falsch ist
Interessant, um sicher zu gehen. Leicht fehlerhaft auf iPhone 4/iOS 6.1.3, mit Bild+1 am rechten Rand,
und eine 2-Finger-Größenänderung löst ein Scrollen zum Ende des Stapels aus. Blamen wir einfach 6.1.3. :-)