DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Web Dev Zone»Comment créer une interface iPhone avec un appui long en Javascript
    Web Dev Zone

    Comment créer une interface iPhone avec un appui long en Javascript

    novembre 18, 2021
    Comment créer une interface iPhone avec un appui long en Javascript
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    Les icônes tremblantes et les appuis longs sont devenus quelque chose que nous connaissons très bien sur nos écrans de téléphone. Sur les iPhones en particulier, le fait de secouer les icônes implique généralement qu’elles sont déplaçables et modifiables, tandis que les appuis longs sont devenus le moyen normal d’obtenir des options supplémentaires.

    Dans ce tutoriel, nous allons voir comment recréer ces effets en Javascript et CSS. Dans ce tutoriel, nous aborderons :

    • Nouvelles fonctionnalités CSS– tels que les flous d’arrière-plan et les boîtes flexibles animées.
    • Appui long— comment créer l’effet d’appui long avec Javascript.
    • Faire glisser— comment créer un simple système de glisser-déposer en Javascript.

    Démo

    Comme toujours, commençons par la démo. C’est ce que nous prévoyons de créer aujourd’hui.

    • Si vous cliquez et appuyez sur une icône pendant une seconde, une fenêtre contextuelle s’affichera.
    • Si vous cliquez et appuyez pendant deux secondes au total, les icônes commenceront à trembler, comme sur iPhone. Cela fonctionnera également sur mobile.

    Étape 1 : HTML

    Dans ce tutoriel, je ne me concentrerai pas trop sur le HTML car il est assez rudimentaire – il suffit de dire que le HTML pour cette démo est composé de :

    • Conteneurs d’icônes – un conteneur div avec toutes les informations sur les icônes individuelles.
    • Une couverture – une couverture div qui se trouve au-dessus de toute la démo, qui sera floue si l’utilisateur appuie longuement pour afficher le sous-menu.
    • Quelques notifications — quelques notifications en bas pour donner des instructions sur ce qu’il faut faire.
    • Un sous-menu — un sous-menu qui se déplace lorsque l’utilisateur clique sur diverses icônes.

    Étape 2 : CSS

    La plupart des CSS sont assez basiques, cependant, je vais citer quelques éléments importants et intéressants que j’ai utilisés et qui sont assez typiques de la conception d’interface utilisateur HTML. Notre objectif est donc de rendre les icônes déplaçables, mais il y a beaucoup de choses qui peuvent affecter cela. D’une part, nous avons une couverture qui apparaît pour brouiller l’arrière-plan. Ensuite, nous avons ces images embêtantes, que la plupart des navigateurs permettent aux utilisateurs de faire glisser.

    Pour contourner la plupart de ces problèmes, nous pouvons utiliser une propriété et une valeur en CSS appelées pointer-events: none;. Cela signifie que l’utilisateur ne peut pas interagir avec nos éléments HTML. Ainsi, sur la couverture floue, nous supprimons les événements de pointeur lorsqu’ils ne sont pas flous et les ajoutons lorsque l’arrière-plan est flou. Cela signifie que l’utilisateur clique normalement sur cet élément HTML, jusqu’à ce que nous voulions rendre l’arrière-plan flou, auquel cas il devient actif :

    #iphone .cover {    
        position: absolute;
        top: -1rem;
        backdrop-filter: blur(4px);
        left: -1rem;
        width: calc(100% + 2rem);
        opacity: 0;
        z-index: 99999;
        height: calc(100% + 2rem);
        transition: all 0.2s ease-out;
        background: rgba(0,0,0,0);
        pointer-events: none; /* No pointer events! */
    }
    [data-dropdown="true"] #iphone .cover {
        pointer-events: all; /* All pointer events */
        opacity: 1; 
    }
    #iphone .icon-container img {
        width: calc(100% + 2px);
        pointer-events: none; /* No pointer events */
    }

    Filtre de toile de fond

    Cela nous amène à une autre propriété CSS qui peut être très utile —backdrop-filter. Avec la prise en charge de tous les principaux navigateurs à l’exception de Firefox, les filtres de fond nous permettent d’ajouter des effets aux éléments derrière une balise HMTL si la balise est légèrement transparente. Dans notre .cover CSS, nous l’avons défini comme suit :

    backdrop-filter: blur(4px);

    Suppression de l’icône d’animation

    Pour toute cette démo, je voulais que la suppression des icônes soit fluide. Les icônes sont disposées selon une flexbox. Pour ce faire, j’ai créé une animation personnalisée qui fait que l’icône est mise à l’échelle jusqu’à zéro (de sorte qu’il semble qu’elle s’éloigne) – puis réduit sa largeur en tandem. L’effet est que les icônes semblent se fermer les unes sur les autres lorsqu’une est supprimée, créant une animation fluide.

    Cette animation est appliquée dans un petit morceau de Javascript lorsque l’utilisateur clique sur un bouton de suppression.

    @keyframes scaleBack {
        0% {
            transform: scale(1);
            width: 5rem;
        }
        40% {
            opacity: 1;
        }
        50% {
            width: 5rem;
            opacity: 0;
            transform: scale(0.0001);
        }
        100% {
            width: 0rem;
            transform: scale(0.0001);
        }
    }

    Points positifs à l’utilisation des transformations

    • Vous permet d’utiliser le positionnement en haut, en bas, à gauche et à droite pour d’autres choses.
    • Utilise l’accélération 3D, il s’anime donc très rapidement !

    Étape 3 : Javascript

    Le Javascript ici n’est pas super compliqué – et en fait, une grande partie de la complexité vient d’essayer de rendre les icônes déplaçables. Il y a essentiellement quelques événements que nous voulons suivre :

    • Lorsque l’utilisateur clique sur une icône, nous voulons mesurer pendant combien de temps, nous pouvons donc afficher la liste déroulante ou l’effet de tremblement.
    • Lorsque l’utilisateur clique sur le bouton, nous voulons supprimer les minuteries pour les appuis longs et réinitialiser tous les autres trackers de mouvement.
    • Lorsque l’utilisateur clique sur le bouton de suppression, nous souhaitons supprimer cette icône.
    • Lorsque l’utilisateur clique sur n’importe quoi sauf sur un bouton, nous voulons supprimer les effets.

    Donc, comme vous l’avez peut-être deviné, nous utilisons des événements de pointeur. Je vous recommande toujours d’essayer d’utiliser des événements de pointeur si vous le pouvez, car ils sont à la fois compatibles avec les appareils mobiles et les ordinateurs de bureau. De cette façon, vous n’avez généralement besoin d’écrire qu’un seul script pour tous les appareils. Les événements de pointeur remplacent les gestionnaires d’événements tels que la souris enfoncée par le pointeur vers le bas.

    État de suivi

    Pour suivre l’utilisateur, nous avons deux états : secouant et déroulant. Nous utilisons des attributs de données dans la balise HTML pour suivre cela – si les icônes tremblent, alors data-shaking="true" sur la balise body, et si une liste déroulante est visible, alors data-dropdown="true" est indiqué sur l’étiquette du corps. Nous procédons de cette façon afin de pouvoir modifier le CSS des éléments en fonction de l’état.

    Nous avons alors la presse longue. Pour gérer les appuis longs, il suffit de :

    • Créer une variable pointeur vers le bas— cette variable est définie sur true immédiatement lorsque l’utilisateur clique et sur false immédiatement lorsqu’il relâche.
    • Créer des délais d’attente— nous vérifions après une seconde et deux secondes si le pointeur vers le bas est vrai. Si c’est le cas, alors nous faisons en sorte que les icônes affichent la liste déroulante ou secouent.
    • Définir une fonction de réinitialisation— Nous réinitialisons toutes les variables si l’utilisateur abandonne l’appui long, afin que nous puissions les réutiliser s’il réessaye.

    Dans le code, cela ressemble à ceci :

    // For selection of the icons and removal icons
    let icons = document.querySelectorAll('.icon-container');
    let removals = document.querySelectorAll('.remove-icon');

    
    // These all store data on the mouse position at different times in the code
    let pointerdown = false;
    let offset = 0;
    let mouseXInit = 0;
    let mouseYInit = 0;
    let mouseX = 0;
    let mouseY = 0;
    let positionX = 0;
    let positionY = 0;
    let currentTop = 0;
    let currentLeft = 0;

    // This is for holding our timers
    let timers = { first: undefined, second: undefined, third: undefined }

    let helpers = {
        reset: function(extended) {
            // This is our reset - it sets everything back to zero, whenever we need to
            // All variables and settings are reset
            mouseX = 0;
            mouseY = 0;
            mouseXInit = 0;
            mouseYInit = 0;
            currentTop = 0;
            currentLeft = 0;
            offset = 0;
            if(typeof timers.first !== "undefined") {
                clearTimeout(timers.first);
            }
            if(typeof timers.second !== "undefined") {
                clearTimeout(timers.second);
            }
            if(typeof timers.third !== "undefined") {
                clearTimeout(timers.third);
            }
            if(typeof extended == "undefined") {
                document.querySelector('.sub-menu').classList.remove('show-sub-menu');
                document.body.setAttribute('data-shaking', false);
                document.body.setAttribute('data-dropdown', false);
                pointerdown = false;
                icons.forEach(function(item) {
                    item.setAttribute('data-selected', false);
                    item.style.top = 0;
                    item.style.left = 0;
                })
            }
        },
        checkPoint: function(x, y, limit) {
            // This checks if the users mouse has moved more than a certain limit. If it has, then they may be dragging..
            // So we don't cause the long press animation
            if(x < limit && x > limit * -1 && y < limit && y > limit * -1) {
                return true;
            } else {
                return false;
            }
        }
    }

    // For every icon 
    icons.forEach(function(item) {
        // Add a pointerdown event
        item.addEventListener('pointerdown', function(e) {
            // Get the click location and set pointerdown to true
            pointerdown = true;
            mouseXInit = e.pageX;
            mouseYInit = e.pageY;
            
            // Get the left and top position of the item, if any
            currentTop = parseFloat(item.style.top) || 0;
            currentLeft = parseFloat(item.style.left) || 0;
            // Set a timer to wait for a hold click
            timers.first = setTimeout(function() {
                // Only do this if pointerdown is true, and if the user hasn't moved more than 10px while clicking down
                if(pointerdown === true && document.body.getAttribute('data-shaking') !== "true" && helpers.checkPoint(mouseX, mouseY, 10)) {
                    
                    // Icon is now selected, and the dropdown should appear
                    item.setAttribute('data-selected', true);
                    document.body.setAttribute('data-dropdown', true);
                    
                    // Find out where exactly the icon is (x, y) coordinates
                    let left = item.getBoundingClientRect().left - document.querySelector('#iphone').getBoundingClientRect().left;
                    let bottom = item.getBoundingClientRect().bottom - document.querySelector('#iphone').getBoundingClientRect().top;
                    // Show the sub menu and move it to where the icon is
                    document.querySelector('.sub-menu').classList.add('show-sub-menu');
                    document.querySelector('.sub-menu').style.left = `${left}px`;
                    document.querySelector('.sub-menu').style.top = `${bottom - 16}px`;

                }
            }, 1000);
            // If the user is still clicking after 2 seconds
            timers.second = setTimeout(function() {
                // Check they are clicking
                if(pointerdown === true && helpers.checkPoint(mouseX, mouseY, 10)) {
                    // Now all icons should shake
                    document.body.setAttribute('data-shaking', true);
                    item.setAttribute('data-dragging', true);
                    // Hide the sub menu
                    document.querySelector('.sub-menu').classList.remove('show-sub-menu');
                    document.body.setAttribute('data-dropdown', false);
                    // Give each animation for shaking a delay, to give the appearance of randomness
                    timers.third = setTimeout(function() {
                        icons.forEach(function(i) {
                            i.style.animationDelay = `${offset}s`;
                            offset += 0.1;
                        })
                    }, 300);
                }
            }, 2000);
            // If the icons are shaking, then the user may be trying to drag this particular icon. Set that icon
            // to have a data-dragging of true. We can use this later
            if(document.body.getAttribute('data-shaking') === "true") {
                item.setAttribute('data-dragging', true);
            }
        });
        // if the user lifts their mouse, then reset everything
        item.addEventListener('pointerup', function() {
            helpers.reset(false);
        });
    })

    Suppression

    Lorsque l’utilisateur clique sur une icône, nous devons alors animer cette icône…

    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.