Maison  >  Article  >  interface Web  >  mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifs

mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifs

怪我咯
怪我咯original
2018-05-28 11:42:074259parcourir


Préface
J'ai regardé VUE au cours des derniers mois, puis j'ai essayé d'implémenter certains composants en utilisant uniquement des js+vue . Composant de sélection de temps sur PC Il s'agit de la première implémentation de la sélection de temps sur PC Cela se fait également du côté mobile, je souhaite donc implémenter le
sélecteur de temps du côté mobile. Je l'ai implémenté sur mobile. L'idée et le processus du sélecteur de temps d'effet spécial à molette de défilement de fin. L'ensemble du composant est construit sur la base de vue-cli
Fonction1. Sélection de l'heure [

A.年月日选择
B.年月日小时分钟选择
Sélection des heures et des minutes D. Sélection des minutes. ]


2. Effet de molette de défilement [

A.构成一个圆环首尾相连
B. Ne constitue pas une connexion de bout en bout]

3. apparaît si l'heure sélectionnée dépasse la plage), minutes Réglage de l'intervalle
4.
Multi-langueRéglage5. Le réglage du format de l'heure répond aux règles de réglage de aaaa/MM/jj HH:mm<.>6. UE est proche de l'effet natif d'iOS
7. L'extension peut non seulement sélectionner l'heure, mais peut également transmettre des données de sélection de liaison personnalisées
Ici, nous parlons principalement de la mise en œuvre de la molette de défilement infinie

Préparation des données 1
Ici, utilisons

pour illustrer
une façon intelligente d'obtenir le nombre de jours dans un mois.



Ici, j'ai utilisé la méthode calculée de vue pour l'implémenter et la mettre dans
dayList () {
       /* get currentMonthLenght */
        let currentMonthLength = new Date(this.tmpYear, this.tmpMonth + 1, 0).getDate();
       /* get currentMonth day */
        let daylist = Array.from({length: currentMonthLength}, (value, index) => {
          return index + 1
        });
        return daylist
      },

yearList
dayList
monthList

hourList
Pour stocker les données de base, la préparation des données se termine ici.
minuteList


StatiqueRéalisation de l'effetIl existe de nombreuses façons de réaliser l'effet statique de la molette de défilement1 Effet visuel 3D [ajouter une ombre]
2. . Effet 3D réel[ CSS3D]


Ma propre implémentation est la deuxième utilisant CSS3D
我把实现效果大致分为上面2种,具体的大家可以自己搜索相关资料,这里展开涉及太多就带过好了

Explication
Nous voyons d'abord l'effet de sélection iOS natif lorsque. saisie Il y a une différence entre la molette de défilement dans la plage de sélection et en dehors de la plage de sélection


mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifsDonc afin d'obtenir cette différence d'effet, j'ai choisi d'utiliser 2 structures dom pour implémentez-le, un dom implémente la molette de défilement et un dom implémente la molette de défilement. DOM réalise l'effet de sélection noire, de sorte qu'une fois lié, il y aura une différence similaire à l'effet d'origine


<.> Installer diverses options du DOM, ici seules celles du jour sont données,

picker-panel

Une boîte la plus à l'extérieur contenant les données du ciel,

box-day

réaliser les 2 lignes sélectionnées,

check-line

Les données de l'effet noir les plus à l'extérieur,

day-list

Partie de la molette de défilement grise

day-wheel


Principalement impliquées dans les attributs CSS
<p class="picker-panel">
<!--other box-->
<p class="box-day">
  <p class="check-line"></p>
  <p class="day-checked">
    <p class="day-list">
      <p class="list-p" v-for="day in renderListDay">
       {{day.value}}
      </p>
    </p>
  </p>
  <p class="day-wheel">
    <p class="wheel-p" v-for="day in renderListDay" transform: rotate3d(1, 0, 0, 80deg) translate3d(0px, 0px, 2.5rem);>
    {{day.value}}
    </p>
  </p>
</p>
<!--other box-->
</p>
.day-wheel{
    position: absolute;
    overflow: visible;
    height: px2rem(68px);
    font-size: px2rem(36px);
    top:px2rem(180px);
    left: 0;
    right: 0;
    color:$unchecked-date;
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    .wheel-p{
     height: px2rem(68px);
     line-height: px2rem(68px);
     position: absolute;
     top:0;
     width: 100%;
     text-align: center;
     -webkit-backface-visibility: hidden;
     backface-visibility: hidden;
     white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
    }
   }


Afficher l'effet 3D,

transform-style: preserve-3d;


La partie derrière le volant est automatiquement masquée

-webkit-backface-visibility: hidden;


Utilisé pour positionner la roue

postition:absolute;


L'angle de rotation de chaque donnée Et le côté de la molette de défilement

Vue
transform: rotate3d(1, 0, 0, 80deg) translate3d(0px, 0px, 2.5rem);
Le rayon du cercle

L'angle et le principe de construction de chaque rotation de données
Comme indiqué ci-dessus
est l'effet de notre vue stéréo avec molette de défilement, r est le 2,5rem dans notre css traduit 3d(0px,0px,2.5rem), mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifsS'il n'y a pas ce CSS, toutes les données seront rassemblées au centre du cercle


L'image ci-dessus n'est pas une rotation (le rouge représente l'effet de données que nous voyons)
mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifs

L'image ci-dessus est tournée (le rouge et l'orange représentent l'effet de données que nous voyons) mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifs
Arc bleu L'angle représenté est le même (cela implique la connaissance des angles), et c'est aussi le angle de rotation visuel, qui est le 80 degrés dans le CSS rotate3d. Ce que je fais est espacé de 20 degrés, de sorte qu'en fait nous faisons uniquement pivoter l'axe des x et tournons d'ailleurs l'angle central du cercle s'étend sur tout l'anneau. Un cercle complet peut contenir des données 360/20, et nous pouvons voir les données frontales à l'œil nu, donc après un certain angle, elles ne devraient pas nous être visibles, et -webkit-backface-visibility: Hidden cette phrase signifie Cela ; travaillé.



L'effet est similaire à l'image ci-dessous

这里我们发现轮子装不完所有数据,而且我们要实现数据循环

Il y a donc une deuxième préparation des données
mise en œuvre de vue.js pour imiter l'expérience de développement de composants de sélection de temps iOS natifsPréparation des données 2

Ici, nous utilisons également notre dayList comme données initiales [1, 2, 3, 4,..., 30, 31] Ici, nous prenons 19 données à chaque fois comme données de rendu, et nous avons besoin de renderListDay le rendu initial est [ 23,24,25,26,27,28,29,30,31,1,2,3,4,5,6,7,8,9,10]Parce que c'est juste de prendre le chiffre du milieu C'est le premier (uniquement lors de l'initialisation)



La méthode de récupération des données est inférieure à 0, en arrière et supérieure à 0, et la récupération en avant,

index
renderListDay(){
        let list = [];
        for (let k = this.spin.day.head; k <= this.spin.day.last; k++) {
          let obj = {
            value: this.getData(k, &#39;day&#39;),
            index: k,
          };
          list.push(obj)
        }
        return list
      },
est supérieure à la longueur des données d'origine. Utilisez le calcul en % pour obtenir l'indice correspondant à la plage normale, donc le spin ci-dessus est notre fourchette pour récupérer les données (initialement de -9 à 9)


L'angle de rotation de chaque donnée (Le demi-cercle supérieur est positif, le demi-cercle inférieur est négatif)

getData(idx, type){
       //...
        else if (type == &#39;day&#39;) {
          return this.dayList[idx % this.dayList.length >= 0 ? idx % this.dayList.length : idx % this.dayList.length + this.dayList.length];
        } 
        //...
      },
<p class="wheel-p" v-for="day in renderListDay" v-bind:data-index="day.index" v-bind:style="{transform: &#39;rotate3d(1, 0, 0, &#39;+ (-day.index)*20%360+&#39;deg) translate3d(0px, 0px, 2.5rem)&#39;}">{{day.value}}{{day.value}}</p>

接着需要旋转到我们需要的角度,跟我们的初始化时间对上,this.orDay-this.DayList[0] 是获取偏移量来矫正角度

this.$el.getElementsByClassName(&#39;day-wheel&#39;)[0].style.transform = &#39;rotate3d(1, 0, 0, &#39; + (this.orDay - this.dayList[0]) * 20 + &#39;deg)&#39;;

增加touch事件
剩下的事就很好处理了,给对应的dom绑定事件根据touchmove的距离来转换成旋转的角度 和check-list的位移这里translateY是用来记录实际移动的距离的,最后输出需要算入偏移量

<p class="box-day" v-on:touchstart="myTouch($event,&#39;day&#39;)" v-on:touchmove="myMove($event,&#39;day&#39;)" v-on:touchend="myEnd($event,&#39;day&#39;)">
  <p class="check-line"></p>
  <p class="day-checked">
    <p class="day-list" data-translateY="0" style="transform: translateY(0rem)">
      <p class="list-p" v-for="day in renderListDay" v-bind:data-index="day.index">
        {{day.value}}
      </p>
    </p>
  </p>
  <p class="day-wheel" style=" transform: rotate3d(1, 0, 0,0deg)">
    <p class="wheel-p" v-for="day in renderListDay" v-bind:data-index="day.index" v-bind:style="{transform: &#39;rotate3d(1, 0, 0, &#39;+ (-day.index)*20%360+&#39;deg) translate3d(0px, 0px, 2.5rem)&#39;}">
     {{day.value}}
    </p>
  </p>
</p>

惯性滚动
这个实现我是用了一个 cubic-bezier(0.19, 1, 0.22, 1)
判断手势是不是flicker 如果是flicker通过一个瞬时速度来算出位移,和时间,然后一次性设置,然后用transition做惯性滚动,
普通拖动 设置1秒
这个实际效果还是有点不好,以后来改进。
其他功能的实现
这里不做详细说明了
总结
自适应方面用了手淘的解决方案
这次实现这个组件最困难的就是实现无限滚动,和无限滚动的渲染数据的构造,接着就是惯性滚动的实现。
已知问题
1.惯性滚动不完美
2.无限滚动实现了。非无限滚动没实现,就是渲染数据就是[1,2,3,4,5,6,7,8,9,10]
3.现在选择必须 年月日 或者年月日小时分钟 不能单独选小时或者分钟

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn