Cet article présente principalement l'implémentation Vue de l'effet de sélection natif iOS et l'analyse des idées d'implémentation. Cet article vous présente de manière très détaillée et a une valeur de référence. Les amis dans le besoin peuvent s'y référer
J'étais. le premier à en implémenter un auparavant. Il existe un plug-in de sélection de temps similaire, mais son champ d'application est trop étroit. Je veux simplement publier cette implémentation récemment et réécrire un composant vue hautement réutilisable.
Supporte Android 4.0 ou supérieur, Safari 7 ou supérieur
Aperçu de l'effet
gitHub
Principalement la structure DOM de la partie de la molette de défilement
<template data-filtered="filtered"> <p class="pd-select-item"> <p class="pd-select-line"></p> <ul class="pd-select-list"> <li class="pd-select-list-item">1</li> </ul> <ul class="pd-select-wheel"> <li class="pd-select-wheel-item">1</li> </ul> </p> </template> props props: { data: { type: Array, required: true }, type: { type: String, default: 'cycle' }, value: {} }
Définissez le style CSS pour la centrer verticalement
.pd-select-line, .pd-select-list, .pd-select-wheel { position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); } .pd-select-list { overflow: hidden; }
Paramètres de style 3D de la molette de défilement
/* 滚轮盒子 */ .pd-select-wheel { transform-style: preserve-3d; height: 30px; } /* 滚轮单项 */ .pd-select-wheel-item { white-space: nowrap; text-overflow: ellipsis; backface-visibility: hidden; position: absolute; top: 0px; width: 100%; overflow: hidden; }
Faites principalement attention à 2 attributs : transform-style :preserve-3d ;backface-visibility :hided ;
Le premier est Disposition 3D, rendant l'interface 3D, la seconde consiste à masquer automatiquement l'arrière de la molette de défilement (la partie rouge dans l'image ci-dessus, le nœud DOM au dos sera automatiquement masqué)
Comment implémenter la molette de défilement 3D
La phrase principale de la transformation css de la boîte : rotate3d(1, 0, 0, x deg);
l'élément utilise principalement cette transformation css : rotate3d(1, 0, 0, xdeg) translation3d(0px, 0px, [x]px) ;
Les 2 images ci-dessus montrent Translate3d(0px, 0px, [x]px); ceci L'effet de la phrase [x] est le rayon du cercle
Comme vous pouvez le voir sur l'image ci-dessus, il suffit de faire pivoter chaque dom lui-même, puis d'utiliser translate3d(0px, 0px, [x]px); Développez chaque dom
pour former un anneau α. angle de rotation de chaque dom. Parce que seulement 0 à 180° est utilisé ici, une boîte est utilisée Installer ces dom
Calculer la hauteur et l'angle des rangées
<🎜. >
Calculez la longueur du troisième côté si les deux côtés et l'angle sont connus~=34pxhttp://tool.520101.com/calculator/sanjiaoxingjiaodu/Implémentation de la molette de défilement infinie
/* 滚轮展示大小限定 */ spin: {start: 0, end: 9, branch: 9} /* 获取spin 数据 */ getSpinData (index) { index = index % this.listData.length return this.listData[index >= 0 ? index : index + this.listData.length] } /* 模运算 获取数组有的索引 这样就构成 圆环了 */
touchend effectue un traitement spécial
Définissez le type setCSS dans touchend pour arrondir les données de défilement, donc que lorsqu'il s'arrêtera, il feraune rotation précise d'une image à la fois
// other code .... /* 计算touchEnd移动的整数距离 */ let endMove = margin let endDeg = Math.round(updateDeg / deg) * deg if (type === 'end') { this.setListTransform(endMove, margin) this.setWheelDeg(endDeg) } else { this.setListTransform(updateMove, margin) this.setWheelDeg(updateDeg) } // other code .... 惯性缓动 // other code .... setWheelDeg (updateDeg, type, time = 1000) { if (type === 'end') { this.$refs.wheel.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)` this.$refs.wheel.style.webkitTransform = `rotate3d(1, 0, 0, ${updateDeg}deg)` } else { this.$refs.wheel.style.webkitTransition = '' this.$refs.wheel.style.webkitTransform = `rotate3d(1, 0, 0, ${updateDeg}deg)` } } setListTransform (translateY = 0, marginTop = 0, type, time = 1000) { if (type === 'end') { this.$refs.list.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)` this.$refs.list.style.webkitTransform = `translateY(${translateY - this.spin.branch * 34}px)` this.$refs.list.style.marginTop = `${-marginTop}px` this.$refs.list.setAttribute('scroll', translateY) console.log('end') } else { this.$refs.list.style.webkitTransition = '' this.$refs.list.style.webkitTransform = `translateY(${translateY - this.spin.branch * 34}px)` this.$refs.list.style.marginTop = `${-marginTop}px` this.$refs.list.setAttribute('scroll', translateY) } } // other code ....
Obtenir la valeur actuellement sélectionnée
/* 在设置完css后获取值 */ setStyle (move, type, time) { // ...other code /* 设置$emit 延迟 */ setTimeout(() => this.getPickValue(endMove), 1000) // ...other code } /* 获取选中值 */ getPickValue (move) { let index = Math.abs(move / 34) let pickValue = this.getSpinData(index) this.$emit('input', pickValue) }
Paramètres d'initialisation
mounted () { /* 事件绑定 */ this.$el.addEventListener('touchstart', this.itemTouchStart) this.$el.addEventListener('touchmove', this.itemTouchMove) this.$el.addEventListener('touchend', this.itemTouchEnd) /* 初始化状态 */ let index = this.listData.indexOf(this.value) if (index === -1) { console.warn('当前初始值不存在,请检查后listData范围!!') this.setListTransform() this.getPickValue(0) } else { let move = index * 34 /* 因为往上滑动所以是负 */ this.setStyle(-move) this.setListTransform(-move, -move) }
Lorsqu'il est affiché sous la forme d'une molette de défilement non infinie
Nous pouvons facilement juger ici, c'est-à-dire que la distance de défilement ne peut pas dépasser la longueur du tableau du nombre d'origine * 34 et ne peut pas être inférieure à 0 (la direction impliquée dans le code réel)/* 根据滚轮类型 line or cycle 判断 updateMove最大距离 */ if (this.type === 'line') { if (updateMove > 0) { updateMove = 0 } if (updateMove < -(this.listData.length - 1) * singleHeight) { updateMove = -(this.listData.length - 1) * singleHeight } } /* 根据type 控制滚轮显示效果 */ setHidden (index) { if (this.type === 'line') { return index < 0 || index > this.listData.length - 1 } else { return false } },
La structure dom a également ajout des réponses correspondantes
<p class="pd-select-item"> <p class="pd-select-line"></p> <p class="pd-select-list"> <ul class="pd-select-ul" ref="list"> <li class="pd-select-list-item" v-for="el,index in renderData " :class="{'hidden':setHidden(el.index)}" :key="index">{{el.value}}</li> </ul> </p> <ul class="pd-select-wheel" ref="wheel"> <li class="pd-select-wheel-item" :class="{'hidden':setHidden(el.index)}" :style="setWheelItemDeg(el.index)" :index="el.index" v-for="el,index in renderData " :key="index">{{el.value}}</li> </ul> </p>
Optimisation du module JavaScript
Comment extraire des bibliothèques tierces à l'aide de webpack
Comment déterminer le type de client en utilisant JS
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!