Cet article présente l'implémentation d'un composant de mise en page simple DrawerLayout (similaire au DrawerLayout d'Android). Apprenons le code d'implémentation du composant de menu coulissant latéral basé sur Vue.js à travers cet article. introduit un simple DrawerLayout (implémentation de composants de mise en page similaires à DrawerLayout d'Android, basé sur Vue.js. Le contenu introduit a été transformé en composant vue-drawer-layout.
Avant-proposSi vous êtes intéressé, veuillez d'abord scanner ce code QR avec votre téléphone portable, ou cliquez sur moi
puis cliquez sur Ouvrir le tiroir ou faites glisser l'avatar dans le coin supérieur gauche de la page vers la droite ou la gauche, et vous pourrez voir l'effet du gif ci-dessous. Ouvrez votre propre QQ mobile, n'est-ce pas ? )
Google appelle officiellement cette mise en page DrawerLayout (barre de navigation du tiroir). Alors, comment y parvenir ? Commençons le film principal !
Structure HTMLLa structure de la page est très simple, avec un tiroir et un conteneur principal, et le contenu peut être personnalisé en externe à l'aide d'emplacements .
Le tiroir est initialement caché à l'extérieur de l'écran de gauche, alors réglez à gauche : -100 % pour le rendre complètement caché à l'extérieur<p class="drawer-layout"> <!--抽屉--> <p class="drawer-wrap"> <slot name="drawer"></slot> </p> <!--主容器--> <p class="content-wrap"> <!--遮罩--> <p class="drawer-mask"></p> <slot name="content"></slot> </p> </p>
Utilisez TouchTout d'abord, déterminez si le navigateur prend en charge touchEvent
let isTouch = 'ontouchstart' in window; let mouseEvents = isTouch ? { down: 'touchstart', move: 'touchmove', up: 'touchend', over: 'touchstart', out: 'touchend' } : { down: 'mousedown', move: 'mousemove', up: 'mouseup', over: 'mouseover', out: 'mouseout' };
Événement de touché de liaison
Premier définir certaines variables. La coordonnée x du doigt pressé est marquée comme startX, la coordonnée x du doigt pendant le glissement est marquée comme nowX et le décalage de coordonnée x du tiroir est marqué comme startPosdocument.addEventListener(mouseEvents.down, initDrag, false);
Déclenchez touchstart Quand, enregistrez la position de départ et liez touchmove Remarque : S'il s'agit de mouseEvent, obtenez la coordonnée x actuelle via e.clientX. S'il s'agit de touchEvent, obtenez la coordonnée x via e.changedTouches[0].clientX.
let startX, nowX, startPos;
const initDrag = function (e) { startX = e.clientX || e.changedTouches[0].clientX; //记录手指按下的位置 startPos = this.pos; //记录drawer的上次位置 document.addEventListener(mouseEvents.move, drag, false); document.addEventListener(mouseEvents.up, removeDrag, false); }.bind(this); const drag = function (e) { nowX = e.clientX || e.changedTouches[0].clientX; //滑动中手指的位置x坐标 let pos = startPos + nowX - startX; pos = Math.min(width, pos); //不能超过滑动最大值 pos = Math.max(0, pos); //不能小于0 this.pos = pos; //设置滚动距离为拖动的距离 }.bind(this);
Distinguer le glissement vertical du glissement horizontalEnsuite, vous rencontrerez un problème, lorsque votre doigt fait défiler le contenu principal verticalement, faites glisser votre doigt à droite Cela fera également glisser le tiroir. À ce stade, vous devez faire une chose : faire la distinction entre le glissement vertical et le glissement horizontal
Bien sûr, il existe de nombreuses façons. Voici une méthode qui utilise les fonctions trigonométriques. pour déterminer
Supposons que chaque flèche dans l'image ci-dessus corresponde à la direction dans laquelle le doigt glisse. La flèche verte signifie que le tiroir peut être retiré et la flèche rouge signifie. qu'il ne peut pas être déplacé (notez que la flèche rouge a également le décalage de la coordonnée x). Autrement dit, lorsque le tiroir ne peut pas être retiré, des événements par défaut doivent être déclenchés, tels que le défilement vertical, etc.
Lorsque le doigt appuie pour déclencher le démarrage tactile, la position initiale P 0 est enregistrée ; lorsque le doigt glisse, le premier mouvement tactile est déclenché, la position P 1 est enregistrée et nous enregistrons le vecteur de P 0 à P 1 comme S (Pardonnez-moi d'être un peintre d'âme)
À ce stade, il est facile de voir que lorsque ∠θ est supérieur à une certaine valeur, telle que 30 degrés, il peut s'agir d'une opération de défilement vertical au lieu de faire glisser le tiroir. Par conséquent, la condition de jugement peut être obtenue en fonction de y/x>tan30°
:
Lorsque isVerticle est vrai, le glissement du tiroir n'est pas effectuéif (isVerticle === undefined) isVerticle = Math.abs(nowY - startY) / Math.abs(nowX - startX) > (Math.sqrt(3) / 3);
Soit le mouvement du tiroir Levez-vous
Nous utilisons l'attribut de transition de CSS3 pour donner au tiroir un effet d'animation de transition Écrivez une classe en mouvement ici
N'oubliez pas d'ajouter une liaison de classe. . Il n'y a pas besoin de transition lors du glissement (pour suivre le doigt), et l'animation de transition n'est nécessaire que lorsque le doigt est relâché..moving transition transform .3s ease
<p class="drawer-wrap" :class="{'moving':moving,'will-change':willChange}" :style="{width:`${width}px`,left:`-${width)}px`,transform:`translate3d(${pos}px,0,0)`}"> <slot name="drawer"></slot> </p>
const removeDrag = function (e) { if (isVerticle !== undefined) { if (!isVerticle) {//当判定为抽屉拖动才进入 let pos = this.pos; this.visible = pos > width * 3 / 5 //当前位置如果大于总宽度的3/5就判定为全部展开抽屉,否则将抽屉弹回隐藏 if (this.pos > 0 && this.pos < width) this.moving = true;//如果位置已经处于最小值或最大值处,不需要有动画效果了 } this.pos = this.visible ? width : 0; } if (!this.moving) { this.willChange = false; //留个悬念 } isVerticle = undefined; //取消touchmove和touchend事件绑定 document.removeEventListener(mouseEvents.move, drag, false); document.removeEventListener(mouseEvents.up, removeDrag, false); }.bind(this);
.will-change
will-change transform
L'attribut CSS will-change fournit aux développeurs Web un moyen d'indiquer au navigateur que Comment les éléments changeront, afin que le navigateur puisse effectuer les préparations d'optimisation correspondantes à l'avance avant que les attributs des éléments ne changent réellement. Ce type d'optimisation peut préparer à l'avance une partie du travail de calcul complexe, rendant la réponse de la page plus rapide et plus sensible.
En fait, on peut informer à l'avance le tiroir du navigateur que le tiroir du navigateur risque d'être déplacé dans touchstart
Bien sûr, au final, n'oubliez pas de supprimer la transition et changera après l'événement de transitionend, pour que le navigateur fasse une pause~const initDrag = function (e) { //... this.willChange = true; }.bind(this);
Y a-t-il autre chose qui peut être optimisé ?
Les principales fonctions mentionnées ci-dessus ont été implémentées pour l'essentiel, mais y a-t-il autre chose qui peut être optimisé ?
Hein ? Qu'est-ce que c'est que le passif
?
网站使用被动事件侦听器以提升滚动性能,在您的触摸和滚轮事件侦听器上设置 passive 选项可提升滚动性能具体看这里
原来这是现代浏览器的一个新特性,我们需要以新的方式来绑定我们的touch事件,当然首先先检测一下是否支持 passive
const supportsPassive = (() => { let supportsPassive = false; try { const opts = Object.defineProperty({}, 'passive', { get: function () { supportsPassive = true; } }); window.addEventListener("test", null, opts); } catch (e) { } return supportsPassive; })();
于是我们的绑定事件代码变成这样
document.addEventListener(mouseEvents.move, drag, supportsPassive ? {passive: true} : false);
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在React Native中使用prop-types如何实现属性确认
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!