2013-04-08 19 views
22

Mi chiedo quali sono i concetti migliori (codice di buona leggibilità, codice di pratica dei parassiti, riusabilità) per creare un dispositivo di scorrimento a loop dell'immagine infinita per un sito Web che utilizza JavaScript/jQuery? Non so come codificare la presentazione ma quale modello corrisponde ai requisiti sopra menzionati. L'obiettivo principale della mia domanda è come disporre le immagini per avere l'impressione di un cursore a ciclo infinito.Concetti di scorrimento loop infinito

Con sguardo al Codice da diversi cursori mi sono imbattuto in due soluzioni:

-change lo z-index di tutte le immagini ogni volta che viene visualizzata l'immagine successiva/precedente.

-cambiare la posizione dell'immagine nel DOM.

Ma esaminare e comprendere il codice degli altri è molto in termini di tempo - è per questo che chiedo a questa domanda :-)

risposta

49

tl; dr - Esempio: http://jsbin.com/ufoceq/8/


Un approccio semplice per creare un cursore di immagine infinito senza troppi sforzi è il seguente: diciamo per semplicità che hai <n> immagini da far scorrere in un ciclo, in modo che dopo lo nth l'immagine da visualizzare è la 1st (e viceversa).

L'idea è di creare un clone di prima e l'ultima immagine in modo che

  • il clone dell'ultima immagine viene anteposto prima del primo;
  • il clone della prima immagine viene aggiunto dopo l'ultimo.

Qualunque sia la quantità delle immagini, è necessario aggiungere al massimo solo 2 elementi clonati.

Sempre per la semplicità, diciamo che tutte le immagini sono 100px larghe e sono avvolte in un contenitore che si sposta a sinistra/destra in una maschera troncata con overflow: hidden. Quindi, tutte le immagini possono essere facilmente allineate in fila con display: inline-block e white-space: nowrap impostate sul contenitore (con flexbox ora è ancora più semplice).

Per n = 4 La struttura DOM sarebbe qualcosa di simile a questo:

offset(px)  0  100  200  300  400  500 
images   | 4c | 1 | 2 | 3 | 4 | 1c 

/*     ^^          ^^ 
     [ Clone of the last image ]    [ Clone of the 1st image ] 
*/ 

All'inizio, il vostro contenitore verrà posizionato con left: -100px (o anche margin-left: -100pxor even better (for a matter of performance)transform: translateX(-100px)), in modo che il dispositivo di scorrimento può mostrare la prima immagine. Per passare da un'immagine ad un'altra dovrai applicare un'animazione javascript sulla stessa proprietà che hai precedentemente scelto.

Quando il cursore è attualmente al l'immagine del 4 °, è necessario passare da un'immagine 4-1c, quindi l'idea è quella di eseguire un callback al termine dell'animazione che presto riposizionare il tuo involucro cursore al Real 1 st offset dell'immagine (ad es.si imposta left: -100px al contenitore)

Questo è analogo quando il cursore è attualmente posizionato sul elemento 1 °: per visualizzare l'immagine precedente è sufficiente per eseguire un'animazione da un'immagine 1-4c e quando l'animazione è stata completato è sufficiente spostare il contenitore in modo che il cursore sia posizionato immediatamente sullo scostamento dell'immagine 4 (ad esempio, è possibile impostare left: -400px nel contenitore).


Potete vedere l'effetto sul violino sopra: questo è il js/jquery codice minimo che ho usato (ovviamente il codice può essere anche ottimizzato in modo che la larghezza delle voci non è codificata nello script)

$(function() { 

    var gallery = $('#gallery ul'), 
     items = gallery.find('li'), 
     len  = items.length, 
     current = 1, /* the item we're currently looking */ 

     first = items.filter(':first'), 
     last = items.filter(':last'), 

     triggers = $('button'); 

    /* 1. Cloning first and last item */ 
    first.before(last.clone(true)); 
    last.after(first.clone(true)); 

    /* 2. Set button handlers */ 
    triggers.on('click', function() { 

    var cycle, delta; 

    if (gallery.is(':not(:animated)')) { 

     cycle = false; 
     delta = (this.id === "prev")? -1 : 1; 
     /* in the example buttons have id "prev" or "next" */ 

     gallery.animate({ left: "+=" + (-100 * delta) }, function() { 

      current += delta; 

      /** 
      * we're cycling the slider when the the value of "current" 
      * variable (after increment/decrement) is 0 or when it exceeds 
      * the initial gallery length 
      */   
      cycle = !!(current === 0 || current > len); 

      if (cycle) { 
       /* we switched from image 1 to 4-cloned or 
        from image 4 to 1-cloned */ 
       current = (current === 0)? len : 1; 
       gallery.css({left: -100 * current }); 
      } 
     }); 
    } 

    }); 
}); 

Come accennato prima, questa soluzione non richiede veramente molto sforzo e si parla di prestazioni, confrontando questo approccio ad un cursore normale senza loop, richiede soltanto fare due inserimento DOM supplementare quando il cursore viene inizializzato e alcuni (abbastanza banale ial) logica aggiuntiva per gestire un ciclo avanti/indietro.

Non so se esiste un approccio più semplice o migliore, ma spero che questo aiuti comunque.

Nota: se avete bisogno di avere anche una galleria reattivo, forse this answer può aiutare anche

+0

Grazie per la spiegazione dettagliata! – user1828928

+0

@ user1828928 se sei interessato ad un esempio dal vivo ho creato un violino breve – fcalderan

+0

Mi dispiace per la prima bandiera. Penso che i fili siano stati incrociati lì, perché hai ragione riguardo allo stato di wiki qui. –

1

Grazie mille di questo articolo! Ho avuto l'aggiornamento e utilizzato sopra il codice. Spero che questo possa aiutare tutti. Scadente sviluppatore.

<!DOCTYPE html> 
 
<html> 
 
<head lang="en"> 
 
    <meta charset="UTF-8"> 
 
    <title>Directive slider</title> 
 
    <style> 
 
     /* 四联切换焦点图 */ 
 
     .slides-wrapper{ position: relative; width: 100%; margin: 10px 0; } 
 
     .gallery { position: relative; width: 1200px; height: 180px; overflow:hidden; } 
 
     .gallery ul { font-size: 0; white-space: nowrap; position: absolute; top: 0; left: -1200px; margin: 0; padding: 0; } 
 
     .gallery li { display: inline-block; vertical-align: top; width: 1200px; height: 180px; white-space: normal; } 
 
     .gallery li img{ width: 298px; height:180px; padding: 1px; } 
 
     .gallery .arrow { background: url(/shop/templates/default/images/home_bg.png) no-repeat; background-size: 150px 223px; width: 35px; height: 70px; position: absolute; z-index: 2; top: 50px; cursor: pointer; opacity: 0;} 
 
     .gallery .prev { background-position: 1px -92px; left: 0;} 
 
     .gallery .next { background-position: -30px -92px; right: 0px;} 
 
    </style> 
 
    <style type="text/css"> 
 
     .demo_wrapper{ 
 
      margin: 0 auto; 
 
      width: 1200px; 
 
     } 
 
     .demo_wrapper .title{ 
 
      text-align: center; 
 
     } 
 
    </style> 
 
</head> 
 
<body> 
 
<div class="demo_wrapper"> 
 
    <div class="title"> 
 
     <h1>Directive slider (Published by fenmingyu)</h1> 
 
    </div> 
 
    <!-- demo content --> 
 
    <div class="slides-wrapper"> 
 
     <div class="gallery" id="top_sale_gallery"> 
 
      <ul> 
 
       <li> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-1.jpg?234" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-2.jpg?752" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-3.jpg?320" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-4.jpg?365" alt=""></a> 
 
       </li> 
 
       <li> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-1.jpg?852" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-2.jpg?746" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-3.jpg?525" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-4.jpg?550" alt=""></a> 
 
       </li> 
 
      </ul> 
 
      <div class='arrow prev'></div> 
 
      <div class='arrow next'></div> 
 
     </div> 
 
     <div class="gallery" id="top_goods_gallery"> 
 
      <ul> 
 
       <li> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-1.jpg?793" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-2.jpg?180" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-3.jpg?550" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-4.jpg?851" alt=""></a> 
 
       </li> 
 
       <li> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-1.jpg?234" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-2.jpg?752" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-3.jpg?320" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-4.jpg?365" alt=""></a> 
 
       </li> 
 
       <li> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-1.jpg?852" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-2.jpg?746" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-3.jpg?525" alt=""></a> 
 
        <a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-4.jpg?550" alt=""></a> 
 
       </li> 
 
      </ul> 
 
      <div class='arrow prev'></div> 
 
      <div class='arrow next'></div> 
 
     </div> 
 
     <div style="clear: both;"></div> 
 
    </div> 
 
</div> 
 

 
</body> 
 
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 
 
<script type="text/javascript"> 
 
    $(function() { 
 
     $.fn.gallery = function(settings) { 
 
      var defaults = { 
 
       time: 3000, 
 
       direction:1 
 
      }; 
 
      var settings = $.extend(defaults, settings); 
 
      var gallery_wrapper = $(this), 
 
       gallery = gallery_wrapper.find('ul'), 
 
       items = gallery.find('li'), 
 
       len  = items.length, 
 
       current = 1, /* the current item we're looking */ 
 
       first = items.filter(':first'), 
 
       last = items.filter(':last'), 
 
       w = gallery.find('li').width(), 
 
       triggers = gallery_wrapper.find('.arrow'); 
 
      var show_slide = function(direction,w){ 
 
       gallery.animate({ left: "+=" + (-w * direction) }, function() { 
 

 
        current += direction; 
 

 
        /** 
 
        * we're cycling the slider when the the value of "current" 
 
        * variable (after increment/decrement) is 0 or when it exceeds 
 
        * the initial gallery length 
 
        */ 
 
        cycle = !!(current === 0 || current > len); 
 

 
        if (cycle) { 
 
         /* we switched from image 1 to 4-cloned or 
 
         from image 4 to 1-cloned */ 
 
         current = (current === 0)? len : 1; 
 
         gallery.css({left: -w * current }); 
 
        } 
 
       }); 
 
      }; 
 
      var picTimer = setInterval(function() { 
 
         show_slide(settings.direction,w); 
 
        }, 
 
        settings.time); 
 
      return this.each(function(){ 
 

 
       /* 1. Cloning first and last item */ 
 
       first.before(last.clone(true)); 
 
       last.after(first.clone(true)); 
 
       /* 2. Set button handlers */ 
 
       triggers.on('click', function() { 
 
        if (gallery.is(':not(:animated)')) { 
 

 
         var cycle = false; 
 
         settings.direction = ($(this).hasClass('prev'))? -1 : 1; 
 
         /* in the example buttons have id "prev" or "next" */ 
 
         show_slide(settings.direction,w); 
 
        } 
 
        clearInterval(picTimer); 
 
        picTimer = setInterval(function() { 
 
           show_slide(settings.direction,w); 
 
          }, 
 
          settings.time); 
 
       }); 
 
       /* hover show arrows*/ 
 
       show_slide(settings.direction,w); 
 

 
       gallery_wrapper.hover(function() { 
 
        $(this).find(".arrow").css("opacity", 0.0).stop(true, false).animate({ 
 
           "opacity": "0.3" 
 
          }, 
 
          300); 
 
       },function(){ 
 
        $(this).find(".arrow").css("opacity", 0.3).stop(true, false).animate({ 
 
           "opacity": "0" 
 
          }, 
 
          300); 
 
       }); 
 
      }); 
 
     }; 
 
     $('#top_goods_gallery.gallery').gallery(); 
 
     $('#top_sale_gallery.gallery').gallery({ 
 
      time: 5000, 
 
      direction:-1 
 
     }); 
 
    }); 
 
</script> 
 
</html>

te e utilizzare questo nel mio progetto.

2

Ho appena creato il dispositivo di scorrimento elemento: il check-out: https://github.com/lingtalfi/jItemSlider/blob/master/README.md

E 'di 600 linee di codice, forse si può semplicemente sfogliarlo.

L'idea alla base è ispirata al dispositivo di scorrimento di Netflix (a partire da 2016-02-24).

Fondamentalmente, utilizza le traduzioni di trasformazione CSS, perché quelle sono le più veloci/più scorrevoli in un browser.

http://eng.wealthfront.com/2015/05/19/performant-css-animations/

Ora il concetto di base dietro il movimento di scorrimento, è che si visualizzare solo la fetta visibile corrente, ma è anche una fetta invisibile a sinistra, e un'altra fetta invisibile sulla destra.

E, si hanno anche due elementi in più, uno su ciascun lato, in modo che i tuoi oggetti simile a questa:

articoli precedenti - prev più voce - articoli principali - il prossimo più voce - prossimi articoli

Sono visibili solo gli oggetti principali. Gli oggetti extra sono parzialmente visibili. Gli elementi precedente e successivo sono invisibili.

Maggiori dettagli qui: https://github.com/lingtalfi/jItemSlider/blob/master/doc/conception.md

Ora, quando si fa scorrere a destra (per esempio), che, fondamentalmente, accodare altri elementi al lato destro, e quindi rimuovere quelli dal lato sinistro.

Questa tecnica è la più grande che ho incontrato finora, perché non si ha a che fare con una lunga lista di elementi (usando la clonazione senza rimuovere gli elementi invisibili), che può rallentare l'animazione.

Nota: il mio primo tentativo di questo dispositivo di scorrimento è stato effettivamente clonazione senza rimuoverlo, funziona, ma non mi piace: https://github.com/lingtalfi/jInfiniteSlider

Inoltre, è elemento basato (piuttosto che i pixel in base), e nel fine, questo è ciò che l'utente si aspetta perché tutto è sempre allineato, come dovrebbe essere.