En la primera parte de este viaje de Draggable, discutimos cómo incluir scripts, investigamos ThrowPropsPlugin, ¡incluyendo los requisitos para comenzar nuestro proyecto con la esperanza de llevarlo a once! Ahora, prepárese para hacer un sistema de menú fuera de lienzo que reaccione al teclado y al tacto.
La demostración completa que estaremos construyendo y discutiendo por el resto de este tutorial también está disponible en CodePen.
Le animo a que pruebe esto por sí mismo en tantos dispositivos como sea posible, especialmente la navegación con el teclado. Cada interacción, ya sea táctil, teclado o mouse, se ha tenido en cuenta, pero como encontrará en nuestro panorama actual, no puede detectar una pantalla táctil y, en ocasiones, intentar hacerlo incluso da como resultado falsos positivos..
Usando el marcado de la parte I comenzaremos agregando un contenedor div
para fines estructurales junto con clases correlacionadas para CSS y JavaScript enganches.
...
Las clases que comienzan con el prefijo "js" significan que estas clases solo aparecen en JavaScript; Eliminarlos dificultaría la funcionalidad. Nunca se utilizan en CSS, lo que ayuda a aislar el foco de las preocupaciones. El contenedor circundante ayudará a controlar el comportamiento de desplazamiento que se describe en la próxima sección de CSS.
Con la base en su lugar, es hora de agregar una capa de ARIA en la parte superior para dar un significado semántico a los lectores de pantalla y usuarios de teclado.
Como el menú estará oculto por defecto aria escondido
atributo está etiquetado cierto
y se actualizará de acuerdo con el estado del menú; falso
para abrir, cierto
para cerrado. Aquí hay una explicación del atributo. aria escondido
por la especificación W3C:
Indica que el elemento y todos sus descendientes no son visibles ni perceptibles para ningún usuario como lo implementó el autor. […] Los autores DEBEN establecer aria-hidden = "true" en el contenido que no se muestra, independientemente del mecanismo utilizado para ocultarlo. Esto permite que las tecnologías de asistencia o los agentes de usuario omitan correctamente los elementos ocultos en el documento. ~ W3C WAI-ARIA Especificaciones
Los autores deben tener cuidado con el contenido que ocultan, haciendo de este atributo una discusión separada fuera del alcance de este artículo. Para aquellos curiosos, la especificación define el atributo con mayor longitud y es algo abultado; algo que no suelo decir a menudo sobre la jerga de especificación.
Nuestra CSS es donde realmente comienza la magia. Tomemos las partes importantes de la demostración que tienen un significado y las desglosamos..
body // scroll fix height: 100%; desbordamiento: oculto; // end scroll fix .app // scroll fix overflow-y: scroll; altura: 100vh; // end scroll fix .dragaebel-nav altura: 100vh; desbordamiento-y: auto; posición: fijo arriba: 0; derecha: 0;
Establecer la altura del cuerpo en 100% permite que el contenedor estire toda la ventana, pero también está desempeñando un papel más importante; lo que nos permite ocultar su desbordamiento.
La solución de desplazamiento por desbordamiento ayuda a controlar cómo se comportan el contenedor principal y la navegación cuando uno de los dos contiene contenido desbordado. Por ejemplo, si el contenedor se desplaza, o el menú, el otro no se desplazará cuando el usuario llegue al final del elemento inicialmente desplazado. Es un comportamiento extraño, que generalmente no se discute, pero permite una mejor experiencia de usuario..
Las unidades de vista son realmente poderosas y juegan un papel vital en la forma en que el contenedor principal contiene contenido desbordado. Las unidades Viewport tienen un soporte maravilloso en los navegadores en estos días y le sugiero que comience a usarlas. He usado unidades vh en la navegación, pero podría haber usado un porcentaje en su lugar. Durante el desarrollo se descubrió que div.app
debe usar vh
las unidades desde el porcentaje no permitirán que el contenido desbordado mantenga el comportamiento de desplazamiento típico; El contenido resulta en ser recortado. Desbordamiento se establece en voluta
en preparación, en caso de que los elementos del menú superen la altura del menú o la altura de la ventana gráfica se acorte.
// Permitir que nav se abra cuando JS falla .no-js .dragaebel-nav: target margin-right: 0; .dragaebel-nav margen-derecha: -180px; ancho: 180px;
los .no-js .nav: target
proporciona acceso a nuestro menú independientemente de si JavaScript falla o está desactivado, por lo tanto, la razón por la que agregamos el valor de ID a la href
atributo del menú desencadenante.
La navegación principal se mueve hacia la derecha a través de un margen negativo que también es el mismo que el ancho de navegación. Para mayor brevedad, estoy escribiendo Vanilla CSS, pero estoy seguro de que podrías escribir algo más sofisticado en un preprocesador de tu elección..
JavaScript es la última parada de este viaje de menú que se puede arrastrar, pero antes de escribir una línea de JS, tendremos que escribir una configuración de patrón de módulo.
var dragaebelMenu = (function () function doSomething () … return init: function () …) (); dragaebelMenu.init (); // iniciarlo!
Para la configuración de configuración definiremos algunas variables para futuras referencias..
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 = [container, nav, logo, nav_trigger], closed_nav = nav.offsetWidth + getScrollBarWidth (); ) ();
La mayoría de estas variables son simplemente agarrar DOM
Elementos, con la excepción de los dos últimos que definen nuestros objetivos GreenSock más el ancho del menú de navegación. La función de utilidad getScrollBarWidth ()
(Fuera de nuestra discusión de hoy) recupera el ancho de la barra de desplazamiento para que podamos ubicar la barra de navegación un poco más allá del ancho de la barra para poder verla cuando se abre el menú. Los objetivos son lo que movemos cuando se abre el menú para permitir que se empuje el contenido adyacente.
Para abreviar, solo discutiré métodos que son extremadamente importantes para la funcionalidad del comportamiento del menú. Todo lo demás que verá en la demostración que no se analiza aquí es el tema "azúcar en la parte superior" que hace que el menú sea aún más poderoso.
menú de funciones (duración) container._gsTransform.x === -closed_nav? TweenMax.to (gs_targets, duration, x: 0, facilidad: Linear.easeIn): TweenMax.to (gs_targets, duración, x: -closed_nav, facilidad: Linear.easeOut);
los menú
La función detecta si la coordenada x del contenedor es igual al estado de navegación cerrada. Si es así, establece los objetivos de nuevo a su posición inicial, de lo contrario los establece en su posición abierta.
función isOpen () return container._gsTransform.x < 0;
Esta es una función de utilidad para verificar el estado del menú. Esto volverá 0
si el menú está cerrado, o un valor negativo si está abierto.
función updateNav (evento) TweenMax.set ([nav, logo, nav_trigger], x: container._gsTransform.x);
Esta es otra función de utilidad que establece la coordenada x del objetivo dentro del parámetro de matriz de .conjunto()
método a la posición x del contenedor cada vez que el onDrag
o onThrowUpdate
evento sucede Esto es parte de la Arrastrable
instancia de objeto.
function enableSelect () container.onselectstart = null; // Se dispara cuando el objeto está siendo seleccionado. TweenMax.set (contenedor, userSelect: 'text'); función disableSelect () TweenMax.set (container, userSelect: 'none'); function isSelecting () // window.getSelection: devuelve un objeto Selection que representa // el rango de texto seleccionado por el usuario o la posición actual // del cursor. return !! window.getSelection (). toString (). length;
Estas funciones ayudan a determinar si alguien está realmente seleccionando texto para habilitar / deshabilitar las capacidades de selección cuando alguien se arrastra por la pantalla. Este no es el comportamiento más ideal para eventos de mouse, pero nuevamente, como ya mencionamos, no se puede detectar una pantalla táctil.
Draggable.create ([objetivos], opciones)
Como comentamos en el tutorial anterior sobre Draggable, esto creará la instancia del objeto Draggable y se enfocará en el DOM
Objetos de nuestra elección que se pueden pasar como una matriz.
Draggable.create ([container], type: 'x', dragClickables: false, throwProps: true, dragResistance: 0.025, edgeResistance: 0.99999999, maxDuration: 0.25, throwResistance: 2000, cursor: 'resize', allowEventDefault: true, encierre : …, OnDrag: updateNav, onDragEnd: function (event) …, liveSnap: function (value) …, onPress: function (event) …, onClick: function (event) …, onThrowUpdate : function () …);
Esta es nuestra instancia completa de Draggable y las propiedades utilizadas. El código de demostración real contiene los comentarios que he dejado para comprender y obtener una mejor perspectiva de lo que cada uno es responsable. Te animo a mirar el código de demostración e incluso te desafío a deconstruir el por qué y cómo.
Este es el final de nuestro viaje a GreenSock y espero que hayas aprendido mucho en el camino. Un agradecimiento especial a Jack y Carl en GreenSock, junto con toda la comunidad de GreenSock, por su increíble ayuda a lo largo de esta serie. Por último, pero no menos importante, muchas gracias a usted, lector por llegar al final de esta serie; felicidades Espero que esta serie haya ayudado a obtener una mejor visión de los poderosos beneficios y capacidades de una increíble biblioteca de animación de JavaScript. Construye cosas increíbles y mantente creativo!