Nella prima parte di questo viaggio Draggable, abbiamo discusso su come includere gli script, abbiamo studiato il ThrowPropsPlugin, inclusi i requisiti per far partire il nostro progetto nella speranza di portarlo a undici! Ora preparatevi a creare un sistema di menu off-canvas che reagisca alla tastiera e al tocco.
La demo completa che svilupperemo e discuteremo per il resto di questo tutorial è disponibile anche su CodePen.
Vi incoraggio a testare questo per voi attraverso il maggior numero di dispositivi possibile, in particolare la navigazione da tastiera. Ogni interazione, che sia touch, tastiera o mouse, è stata presa in considerazione, ma come puoi trovare nel nostro panorama corrente non puoi rilevare un touchscreen e a volte provando a farlo anche i risultati in falsi positivi.
Usando il markup dalla parte I inizieremo aggiungendo un contenitore div
per scopi strutturali insieme alle classi di correlazione per i ganci CSS e JavaScript.
... ...
Le classi che iniziano con il prefisso "js" significano che queste classi appaiono solo in JavaScript; rimuovendoli si ostacolerebbe la funzionalità. Non vengono mai utilizzati nei CSS, contribuendo a isolare il focus delle preoccupazioni. Il contenitore circostante aiuterà a controllare il comportamento di scorrimento che viene discusso nella prossima sezione CSS.
Con le fondamenta in atto, è ora di aggiungere uno strato di ARIA in alto per dare un significato semantico agli screen reader e agli utenti di tastiera.
Dal momento che il menu sarà nascosto di default il Aria-nascosto
l'attributo è etichettato vero
e verrà aggiornato di conseguenza in base allo stato del menu; falso
per aperto, vero
per chiuso. Ecco una spiegazione dell'attributo Aria-nascosto
secondo le specifiche del W3C:
Indica che l'elemento e tutti i suoi discendenti non sono visibili o percepibili da alcun utente come implementato dall'autore. [...] Gli autori DEVONO impostare aria-hidden = "true" sul contenuto che non viene visualizzato, indipendentemente dal meccanismo utilizzato per nasconderlo. Ciò consente alle tecnologie assistive o ai programmi utente di saltare correttamente gli elementi nascosti nel documento. ~ W3C WAI-ARIA Spec
Gli autori dovrebbero prestare attenzione ai contenuti che nascondono, rendendo questo attributo una discussione separata al di fuori dello scopo di questo articolo. Per chi è curioso, la specifica definisce l'attributo in un'ulteriore lunghezza ed è alquanto grokkable; qualcosa che di solito non dico spesso sul gergo delle specifiche.
Il nostro CSS è dove la magia inizia davvero. Prendiamo le parti importanti dalla demo che hanno un significato e scomposizione.
body // scroll fix height: 100%; overflow: nascosto; // end scroll fix .app // scroll fix overflow-y: scroll; altezza: 100 vh; // end scroll fix .dragaebel-nav height: 100vh; overflow-y: auto; posizione: fissa; inizio: 0; a destra: 0;
Impostando l'altezza del corpo al 100%, il contenitore può allungare l'intera finestra, ma sta anche giocando una parte più importante; permettendoci di nascondere il suo trabocco.
La correzione per lo scorrimento in eccesso aiuta a controllare il comportamento del contenitore primario e della navigazione quando uno contiene contenuto in eccesso. Ad esempio, se si scorre il contenitore o il menu, l'altro non scorrerà quando l'utente raggiunge la fine dell'elemento a scorrimento iniziale. È un comportamento strano, non in genere discusso, ma offre un'esperienza utente migliore.
Le unità Viewport sono davvero potenti e svolgono un ruolo fondamentale nel modo in cui il contenitore primario contiene contenuti in eccesso. Le unità Viewport hanno un ottimo supporto tra i browser in questi giorni e consiglio vivamente di iniziare a usarle. Ho usato unità vh sul nav, ma avrei potuto usare una percentuale invece. Durante lo sviluppo è stato scoperto div.app
deve usare vh
le unità poiché la percentuale non consente al contenuto in eccesso di mantenere il tipico comportamento di scorrimento; il contenuto risulta essere tagliato. Overflow è impostato su scorrere
in preparazione nel caso in cui le voci del menu superano l'altezza del menu o l'altezza della finestra diventa stretta.
// Permetti al nav di aprirsi quando JS fallisce .no-js .dragaebel-nav: target margin-right: 0; .dragaebel-nav margin-right: -180px; larghezza: 180 px;
Il .no-js .nav: target
fornisce l'accesso al nostro menu, indipendentemente dal fatto che JavaScript non funzioni o sia disattivato, da qui il motivo per cui abbiamo aggiunto il valore dell'ID al href
attributo del trigger del menu.
La navigazione principale viene spostata a destra tramite un margine negativo che è uguale alla larghezza del nav. Per brevità sto scrivendo Vanilla CSS, ma sono sicuro che potresti scrivere qualcosa di più elaborato in un pre-processore a tua scelta.
JavaScript è l'ultima fermata di questo percorso di menu trascinabile, ma prima di scrivere una riga di JS sarà necessario scrivere un'impostazione del modello di modulo.
var dragaebelMenu = (function () function doSomething () ... return init: function () ...) (); dragaebelMenu.init (); // avvialo!
Per l'impostazione della configurazione definiremo alcune variabili per riferimento futuro.
var dragaebelMenu = (function () var container = document.querySelectorAll ('. js-dragsurface') [0], nav = document.querySelectorAll ('. js-dragnav') [0], nav_trigger = document.querySelectorAll (' .js-dragtoggle ') [0], logo = document.querySelectorAll ('. js-draglogo ') [0], gs_targets = [contenitore, nav, logo, nav_trigger], closed_nav = nav.offsetWidth + getScrollBarWidth (); ) ();
La maggior parte di queste variabili sta semplicemente afferrando DOM
elementi, ad eccezione degli ultimi due che definiscono i nostri obiettivi GreenSock più la larghezza del menu di navigazione. La funzione di utilità getScrollBarWidth ()
(al di fuori della nostra discussione di oggi) recupera la larghezza della barra di scorrimento in modo che possiamo posizionare il nav appena oltre la larghezza della barra stessa per vederlo quando si apre il menu. Gli obiettivi sono ciò che ci muoviamo quando il menu si apre per consentire il contenuto adiacente da spingere.
Per farla breve discuterò solo i metodi che sono estremamente importanti per la funzionalità del comportamento del menu. Tutto il resto che vedrai nella demo non discusso qui è il "sugar on top" che rende il menu ancora più potente.
menu funzione (durata) container._gsTransform.x === -closed_nav? TweenMax.to (gs_targets, duration, x: 0, ease: Linear.easeIn): TweenMax.to (gs_targets, duration, x: -closed_nav, ease: Linear.easeOut);
Il menu
la funzione rileva se la coordinata x del contenitore è uguale allo stato di navigazione chiuso. In tal caso, riporta gli obiettivi nella loro posizione iniziale, altrimenti li imposta nella loro posizione aperta.
function isOpen () return container._gsTransform.x < 0;
Questa è una funzione di utilità per controllare lo stato del menu. Questo tornerà 0
se il menu è chiuso, o un valore negativo se è aperto.
function updateNav (event) TweenMax.set ([nav, logo, nav_trigger], x: container._gsTransform.x);
Questa è un'altra funzione di utilità che imposta la coordinata x del bersaglio all'interno del parametro dell'array del .impostato()
metodo alla posizione x del contenitore ogni volta che onDrag
o onThrowUpdate
l'evento accade. Questo fa parte del trascinabili
istanza di oggetto.
function enableSelect () container.onselectstart = null; // Si attiva quando viene selezionato l'oggetto. TweenMax.set (contenitore, userSelect: 'text'); function disableSelect () TweenMax.set (container, userSelect: 'none'); function isSelecting () // window.getSelection: restituisce un oggetto Selection che rappresenta // l'intervallo di testo selezionato dall'utente o la posizione corrente // del cursore. return !! window.getSelection (). toString (). length;
Queste funzioni aiutano a determinare se qualcuno sta realmente selezionando il testo per abilitare / annullare le funzionalità di selezione quando qualcuno si trascina sullo schermo. Questo non è il comportamento più ideale per gli eventi del mouse, ma ancora, come abbiamo già detto, non è possibile rilevare un touch screen.
Draggable.create ([target], opzioni)
Come abbiamo discusso nel precedente tutorial su Draggable, questo creerà l'istanza dell'oggetto Draggable e targetizzerà il DOM
oggetti di nostra scelta che possono essere passati come un array.
Draggable.create ([container], type: 'x', dragClickables: false, throwProps: true, dragResistance: 0.025, edgeResistance: 0.99999999, maxDuration: 0.25, throwResistance: 2000, cursore: 'resize', allowEventDefault: true, bounds : ..., onDrag: updateNav, onDragEnd: function (event) ..., liveSnap: function (value) ..., onPress: function (evento) ..., onClick: function (event) ..., onThrowUpdate : funzione() … );
Questa è la nostra intera istanza Draggable e le proprietà utilizzate. Il codice demo attuale contiene commenti che ho lasciato per capire e ottenere una migliore perspicacia su ciò che ciascuno è responsabile. Ti incoraggio a esaminare il codice demo e persino a sfidarti a decostruire il perché e il modo.
Questa è la fine del nostro viaggio GreenSock e spero che tu abbia imparato un sacco lungo la strada. Un ringraziamento speciale a Jack e Carl di GreenSock, insieme all'intera comunità di GreenSock, per il loro incredibile aiuto in questa serie. Ultimo, ma non meno importante, un enorme grazie a te, lettore per aver raggiunto la fine di questa serie; congratulazioni! Spero che questa serie abbia aiutato a vedere meglio i potenti benefici e le capacità di una fantastica libreria di animazioni JavaScript. Crea cose fantastiche e resta creativo!