Cet article présente principalement le framework vue mobile UI pour implémenter le composant de menu latéral de type QQ. Il est très bon et a une valeur de référence. Les amis dans le besoin peuvent s'y référer
Des entretiens récents ont révélé que de nombreux fronts. Je n'ai jamais eu d'expérience dans l'écriture de plug-ins. J'ai essentiellement utilisé Baidu sur Internet. J'ai donc l'intention d'écrire une série d'articles pour apprendre à des frères qui n'ont jamais écrit de composants comment écrire des plug-ins étape par étape. Cette série d'articles est tous basée sur VUE et le contenu principal est le même. Après l'avoir compris, vous pouvez rapidement le réécrire en composants tels que React, Angular ou Small Programs. Cet article est le premier et concerne un composant de menu latéral similaire à QQ.
Affichage des effets
Laissons tout le monde jeter un œil à l'affichage des effets pour savoir ce que nous voulons faire. L'image est un peu floue. . Commençons par :
Commencer à créer
Structure DOM
Il devrait y avoir deux conteneurs dans la structure globale : 1. Conteneur de menu 2. Conteneur de page principale donc la structure actuelle du DOM est la suivante :
<template> <p class="r-slide-menu"> <p class="r-slide-menu-wrap"></p> <p class="r-slide-menu-content"></p> </p> </template>
Afin de rendre personnalisable le contenu du menu et le contenu du thème, nous ajoutons deux emplacements aux deux conteneurs : le contenu principal est placé dans l'emplacement par défaut, et le menu est placé dans l'emplacement du menu :
<template> <p class="r-slide-menu"> <p class="r-slide-menu-wrap"> <slot name="menu"></slot> </p> <p class="r-slide-menu-content"> <slot></slot> </p> </p> </template>
style css
Scss est utilisé dans mon projet, le code est le suivant :
<style lang="scss"> @mixin one-screen { position: absolute; left:0; top:0; width:100%; height:100%; overflow: hidden; } .r-slide-menu{ @include one-screen; &-wrap, &-content{ @include one-screen; } &-transition{ -webkit-transition: transform .3s; transition: transform .3s; } } </style>
À ce stade, nous avons deux conteneurs absolument positionnés
javascript
Commençons maintenant l'écriture formelle du code. Nous clarifions d'abord la logique d'interaction suivante :
Lorsque le doigt glisse vers la gauche et la droite, le conteneur principal et le conteneur de menu se déplacent avec le mouvement du doigt
Lorsque le doigt se déplace plus loin que le menu La page ne peut pas continuer à glisser vers la droite lorsque la largeur du conteneur
Lorsque le doigt se déplace vers la gauche pour que la distance de déplacement entre le menu et la page revient à zéro, la page ne peut pas continuer à se déplacer vers la gauche
Lorsque le doigt est relâché de l'écran, si la page glisse au-delà d'une certaine distance (proportion de toute la largeur du menu), tout le menu sera ouvert. S'il est inférieur à une certaine distance, le menu sera fermé
Il faut donc maintenant pouvoir paramétrer la personnalisation. largeur du menu lors de l'utilisation du composant et le rapport entre la valeur critique qui déclenche la fermeture du menu et la largeur du menu. En même temps, nous devons ajouter un événement tactile au conteneur principal. le conteneur de menu et le conteneur principal. Ajoutez un style pour contrôler leur mouvement, et contrôlez le mouvement du conteneur en contrôlant ce style
<template> <p class="r-slide-menu"> <p class="r-slide-menu-wrap" :style="wrapStyle"> <slot name="menu"></slot> </p> <p class="r-slide-menu-content" :style="contentStyle" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"> <slot></slot> </p> </p> </template> <script> export default { props: { width: { type: String, default: '250' }, ratio: { type: Number, default: 2 } }, data () { return { isMoving: false, transitionClass: '', startPoint: { X: 0, y: 0 }, oldPoint: { x: 0, y: 0 }, move: { x: 0, y: 0 } } }, computed: { wrapStyle () { let style = { width: `${this.width}px`, left: `-${this.width / this.ratio}px`, transform: `translate3d(${this.move.x / this.ratio}px, 0px, 0px)` } return style }, contentStyle () { let style = { transform: `translate3d(${this.move.x}px, 0px, 0px)` } return style } }, methods: { touchstart (e) {}, touchmove (e) {}, touchend (e) {} } }
Ensuite, nous mettra en œuvre notre fonction principale de traitement des événements tactiles, la logique de l'événement est la suivante :
Le moment où le doigt est enfoncé, le point touché par le doigt actuel et la position du doigt actuel le conteneur principal est enregistré
Lorsque le doigt bouge, obtenez la position du point mobile
Calculez la distance des axes X et Y du courant mouvement du point du doigt, si la distance de mouvement X est supérieure à la distance de mouvement Y. Ensuite, il est déterminé comme étant un mouvement horizontal, sinon c'est un mouvement vertical
S'il s'agit d'un mouvement horizontal , il est jugé que la distance de déplacement actuelle se situe dans un intervalle de mouvement raisonnable (0 à la largeur du menu), et si c'est le cas, changez la position des deux conteneurs (empêchez que d'autres événements sur la page soient déclenchés pendant le mouvement)
Le doigt quitte l'écran : si la distance de déplacement cumulée dépasse la valeur critique, utilisez l'animation pour ouvrir le menu, sinon fermez le menu
touchstart (e) { this.oldPoint.x = e.touches[0].pageX this.oldPoint.y = e.touches[0].pageY this.startPoint.x = this.move.x this.startPoint.y = this.move.y this.setTransition() }, touchmove (e) { let newPoint = { x: e.touches[0].pageX, y: e.touches[0].pageY } let moveX = newPoint.x - this.oldPoint.x let moveY = newPoint.y - this.oldPoint.y if (Math.abs(moveX) < Math.abs(moveY)) return false e.preventDefault() this.isMoving = true moveX = this.startPoint.x * 1 + moveX * 1 moveY = this.startPoint.y * 1 + moveY * 1 if (moveX >= this.width) { this.move.x = this.width } else if (moveX <= 0) { this.move.x = 0 } else { this.move.x = moveX } }, touchend (e) { this.setTransition(true) this.isMoving = false this.move.x = (this.move.x > this.width / this.ratio) ? this.width : 0 }, setTransition (isTransition = false) { this.transitionClass = isTransition ? 'r-slide-menu-transition' : '' }
Ci-dessus, il y a une fonction setTransition dans ce code principal. La fonction de cette fonction est de donner un message au conteneur lorsque le doigt part. Ajoutez un attribut de transition à l'élément pour autoriser. le conteneur doit avoir une animation de transition pour compléter l'animation de fermeture ou d'ouverture ; par conséquent, l'attribut de transition sur le conteneur doit être supprimé au moment où le doigt est enfoncé pour éviter la mauvaise expérience de glissement retardé du conteneur et du doigt. pendant le processus de glissement. Pour dernier rappel, la raison pour laquelle Translate3d est utilisé à la place de Translate dans le code est d'activer l'accélération 3D de l'animation sur les téléphones mobiles et d'améliorer la fluidité de l'animation. Le code final est le suivant :
<template> <p class="r-slide-menu"> <p class="r-slide-menu-wrap" :class="transitionClass" :style="wrapStyle"> <slot name="menu"></slot> </p> <p class="r-slide-menu-content" :class="transitionClass" :style="contentStyle" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"> <slot></slot> </p> </p> </template> <script> export default { props: { width: { type: String, default: '250' }, ratio: { type: Number, default: 2 } }, data () { return { isMoving: false, transitionClass: '', startPoint: { X: 0, y: 0 }, oldPoint: { x: 0, y: 0 }, move: { x: 0, y: 0 } } }, computed: { wrapStyle () { let style = { width: `${this.width}px`, left: `-${this.width / this.ratio}px`, transform: `translate3d(${this.move.x / this.ratio}px, 0px, 0px)` } return style }, contentStyle () { let style = { transform: `translate3d(${this.move.x}px, 0px, 0px)` } return style } }, methods: { touchstart (e) { this.oldPoint.x = e.touches[0].pageX this.oldPoint.y = e.touches[0].pageY this.startPoint.x = this.move.x this.startPoint.y = this.move.y this.setTransition() }, touchmove (e) { let newPoint = { x: e.touches[0].pageX, y: e.touches[0].pageY } let moveX = newPoint.x - this.oldPoint.x let moveY = newPoint.y - this.oldPoint.y if (Math.abs(moveX) < Math.abs(moveY)) return false e.preventDefault() this.isMoving = true moveX = this.startPoint.x * 1 + moveX * 1 moveY = this.startPoint.y * 1 + moveY * 1 if (moveX >= this.width) { this.move.x = this.width } else if (moveX <= 0) { this.move.x = 0 } else { this.move.x = moveX } }, touchend (e) { this.setTransition(true) this.isMoving = false this.move.x = (this.move.x > this.width / this.ratio) ? this.width : 0 }, // 点击切换 switch () { this.setTransition(true) this.move.x = (this.move.x === 0) ? this.width : 0 }, setTransition (isTransition = false) { this.transitionClass = isTransition ? 'r-slide-menu-transition' : '' } } } </script> <style lang="scss"> @mixin one-screen { position: absolute; left:0; top:0; width:100%; height:100%; overflow: hidden; } .r-slide-menu{ @include one-screen; &-wrap, &-content{ @include one-screen; } &-transition{ -webkit-transition: transform .3s; transition: transform .3s; } } </style>
Ce qui précède est ce que j'ai compilé pour tout le monde. J'espère qu'il sera utile à tout le monde à l'avenir.
Articles connexes :
Explication détaillée de l'utilisation d'Angular CLI pour générer du code à partir de plans
Une brève discussion sur la méthode simple d'utilisation de Baidu Maps sous Vue
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!