Heim > Artikel > Web-Frontend > JS ermöglicht das Durchsuchen von Bildern im Vollbildmodus mit unbegrenztem Wischen
Unendliche Ladestrategie
Da es sich um ein unendliches Wischen handelt, ist es nicht möglich, alle Bilder zu erhalten gleichzeitig geladen werden; da ein Scratching-Effekt vorhanden sein muss, müssen die linke und rechte Seite des aktuellen Bildes vorgeladen werden. Daher können Sie drei Bilder als Fenster verwenden und die Rotationsstrategie verwenden, um eine unendliche Wischliste zu erhalten.
<p class="lightbox"> <p class="container"> <p class="lightbox-item prev"></p> <p class="lightbox-item current"></p> <p class="lightbox-item next"></p> </p> </p>
Das .lightbox-Vollbildlayout, das .lightbox-Element enthält das vorherige, aktuelle und nächste Bild. Immer wenn das Bild gewischt wird, ändern wir das nächste Bild zum vorherigen Bild, das aktuelle Bild zum vorherigen Bild, das ursprüngliche vorherige Bild zum nächsten Bild und laden die nächste Bildressource vor.
Beachten Sie, dass hier eine zusätzliche .container-Ebene hinzugefügt wird, die alle Bilder umschließt. Auf diese Weise können wir das Bild animieren, wenn wir es als Ganzes verschieben möchten.
Layoutstil
Wir stellen die .lightbox auf Vollbild ein und platzieren .prev links vom aktuellen Bildschirm und .neben rechts.
.lightbox, .container .lightbox-item{ position: fixed; left: 0; right: 0; top: 0; background-color: #000; } .container{ position: absolute; } .lightbox-item{ /* 我们用背景图来显示图片 */ position: absolute; background-repeat: no-repeat; background-position: center; background-size: contain; } .lightbox-item.prev{ left: -100%; right: 100%; } .lightbox-item.next{ left: 100%; right: -100%; }
Unter einigen Browsern (z. B. einem bestimmten integrierten Browser von Samsung) wird festgestellt, dass der Seiteninhalt tatsächlich dreimal so breit ist wie die Seite. Daher wurde die Seite so verbreitert, dass alle drei Bilder angezeigt wurden. Das Festlegen eines Überlaufs kann dieses Problem beheben:
.lightbox{ overflow: hidden; }
Berührungsereignisse binden
Der Schlüssel zum Bildwischeffekt Es liegt im Touch-Ereignis des Benutzers. Da es sich um ein Vollbild-Browsing handelt, kann es direkt an das Fenster gebunden werden. Bei der Bindung an das Fenster müssen wir jedoch auf Konflikte und Bindungsprobleme achten. Sie können die von Ihnen registrierte Funktion entfernen oder einen Namensraum hinzufügen, zum Beispiel:
$(window) .on('mouseup.lightbox touchend.lightbox', onTouchEnd) .on('mousemove.lightbox touchmove.lightbox', onTouchMove) .on('mousedown.lightbox touchstart.lightbox', onTouchBegin) $(window) .off('mouseup.lightbox touchend.lightbox') .off('mousemove.lightbox touchmove.lightbox') .off('mousedown.lightbox touchstart.lightbox')
Hier gibt es 6 Schlüsselereignisse, nämlich:
Mousedown, Mousemove, Mouseup: Maus drücken, bewegen und entspannen;
touchbegin, touchmove, touchend: berühren, drücken, verschieben und verlassen.
Bildschiebeanimation
Tatsächlich ist das Bild nicht wie der Finger animiert bewegt sich, einfach seine Position aktualisieren, wenn touchmove.
// 起始位置,划动距离 var beginX, translateX; function onTouchBegin(e){ beginX = getCursorX(e); } function getCursorX(e) { // 如果是鼠标事件 if (['mousemove', 'mousedown'].indexOf(e.type) > -1) { return e.pageX; } // 如果是触摸事件 return e.changedTouches[0].pageX; } function onTouchMove(e){ translateX = getCursorX(e) - beginX; $('.container') .attr('transform:translate3d(' + translateX + ')'); .attr('-webkit-transform:translate3d(' + translateX + ')'); }
Die -webkit-transformation hier dient der Kompatibilität mit dem Android UC-Browser, und alles andere scheint in Ordnung zu sein. Beachten Sie außerdem, dass Translate3d die Hardwarebeschleunigung ermöglicht, TranslateX hingegen nicht. Daher ist die Leistung von TranslateX in normalen Android-Browsern sehr schlecht.
Wenn Kompatibilitätsprobleme auftreten, möchte ich unbedingt über Tianshas UC sprechen. Aber dann habe ich darüber nachgedacht, zumindest muss es nicht mit IE6 kompatibel sein, und ich muss mich nicht zu sehr beschweren.
Bestimmen des gleitenden Ziels
Dem obigen Code fehlt noch ein onTouchEnd, das heißt, der Benutzer lässt los Was passiert, nachdem eine bestimmte Distanz zurückgelegt wurde? Wenn der Wischabstand groß genug ist, setzen Sie die Animation fort und blättern Sie zum nächsten Bild, andernfalls kehren Sie zur ursprünglichen Position zurück. Gleichzeitig muss auch die Wischgeschwindigkeit erfasst werden. Wenn die Entfernung kurz, aber die Geschwindigkeit sehr groß ist, sollte auch ein Bildwechsel durchgeführt werden.
Haben wir hier noch nie auf die Details geachtet, wenn wir normalerweise Bilder verschieben
Zeichnen Sie die Startzeit in onTouchBegin auf, und in onTouchEnd ist das kalkulierbar Geschwindigkeit.
var beginTime, endTime; function onTouchBegin(e){ beginTime = Date.now(); } function onTouchEnd(e){ endTime = Date.now(); animateTo(getTarget()); }
Hier wird mit getTarget() das zu wischende Bild berechnet, während animateTo eine Wischanimation aufruft.
function getTarget(){ // 首先检测划动距离,返回 -1, 0, 1 表示上一张,当前,下一张 var direction = getDirection(translateX, 0.3 * $(window).width()); // 如果划动距离检测为0,继续检测速度 if (direction === 0) { var deltaT = Math.max(endTime - beginTime, 1); var v = translateX / deltaT; direction = getDirection(v, 0.3); } return ['.prev', '.current', '.next'][direction + 1]; } function getDirection(offset, max) { if (offset > max) return -1; if (offset < -max) return 1; return 0; }
Animation nach Ende des Strichs
Nachdem der Wischvorgang abgeschlossen ist, müssen wir den .container zum Zielbild schieben. Um zu vermeiden, dass das aktuelle Bild abrupt durch das Zielbild ersetzt wird, setzen wir die Transformationsanimation auf die Zielposition und ersetzen sie dann leise. Das Folgende ist die Hauptlogik von animateTo:
// 计算划动到的目标图片对应的translateX var translateX = $(window).width() * (1 - idx); $('.container').animate({ 'transform': 'translate3d(' + translateX + 'px, 0px, 0px)' '-webkit-transform': 'translate3d(' + translateX + 'px, 0px, 0px)' }, { duration: 1000, complete: function() { // 动画结束后进行图片轮换 var $wps = $('.container').find('.lightbox-item'); var $prev = $wps.filter('.prev'); var $curr = $wps.filter('.current'); var $next = $wps.filter('.next'); if (target === '.prev') { idx--; $prev.attr('class', 'lightbox-item current'); $curr.attr('class', 'lightbox-item next'); $next.attr('class', 'lightbox-item prev'); prefetch('.prev', idx - 1); } else if (target === '.next') { idx++; $next.attr('class', 'lightbox-item current'); $curr.attr('class', 'lightbox-item prev'); $prev.attr('class', 'lightbox-item next'); prefetch('.next', idx + 1); } $(.container).css('transform', 'none'); $(.container).css('-webkit-transform', 'none'); } });
Erinnern Sie sich? Wir müssen das nächste Bild nach dem Verschieben vorab abrufen. Auf diese Weise kann das Bild kontinuierlich gescrollt werden. Der Vorabrufvorgang besteht darin, die nächste Bildadresse vom Server vorab abzurufen und dann das älteste Bild im Schiebefenster zu ersetzen. Die spezifische Implementierung hängt auch mit dem Server zusammen, daher werde ich hier nicht auf Details eingehen.
注意!当动画结束时对.prev,.current,.next进行轮换并重置transform。 如果重置为translate3d(0,0,0)则动画仍会继续,页面就会跳一下。 如果重置为none则会非常平滑,同时别忘了-webkit-transform来兼容更多浏览器。
TouchBegin 的兼容性
在Android ICS下如果touchbegin和第一个touchmove中都未调用 preventDefault, 后续的touchmove和touchend就不会被触发。 解决办法当然是在onTouchBegin中进行preventDefault(), 然而这样click事件(点击关闭全屏啊!)就不会被触发了:
function onTouchBegin(e) { e.preventDefault(); }
所以我们需要在onTouchMove中来判断这是否是一个Click,并手动触发它的行为。
function onTouchMove(e){ if(isClick()) onClick(); function isClick() { var deltaT = endTime - beginTime; var deltaX = Math.abs(translateX); // 时间很短,并且移动距离很小,那么应该是个点击! return deltaT < 700 && deltaX < 7; } }
图片渐进载入
当网速很慢时,连续划动就可能使得旧的图片显示出来(因为预取请求仍未返回)。 常见的一个实践是:立即使用一个已经载入的图片来作为Placeholder, 当目标图片载入后用它替换掉当前的Placeholder。
function loadImage($img, src){ // 先设置一个Placeholder $img.attr('src', 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='); // 载入图片到临时变量 var tmp = new Image(); tmp.onload = function(){ // 资源载入后,将资源显示到目标的img $img.src = src; }; tmp.src = src; }
设置背景图与设置src属性一样,均可以使用该策略。浏览器会复用那个资源。
图片到底提示
在第一张图片右划和最后一张图片左划时,应当给出提示。 可以做一张带有提示信息的Placeholder:
$lightbox.attr('style', 'top:0;left:0;right:0;bottom:0;'); $lightbox.append($('<p class="alert-nomore">').html('没有更多了..'));
然后让文字居中:
.lightbox-item .alert-nomore{ position: absolute; text-align: center; bottom: 50%; left: 0; right: 0; color: #777; font-size: 20px; }
Das obige ist der detaillierte Inhalt vonJS ermöglicht das Durchsuchen von Bildern im Vollbildmodus mit unbegrenztem Wischen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!