Vue.js to realize the _javascript skill of imitating native iOS time selection component instance code

Source: Internet
Author: User
Tags visibility

Objective

Have been watching Vue in recent months, and then try to implement certain components using only native Js+vue.

PC end Time Selection component This is the first implementation of the PC on the time selection, usually the mobile end is also doing, so I want to realize the mobile end of the time selector, the following share I realize the mobile end of the wheel effect time selector thinking and process. The entire component is built based on VUE-CLI.

Function

1. Time selection [ A.年月日选择 B.年月日小时分钟选择 C. Hour minutes Select D. Minutes Selection]

2. Roller effect [ A.构成一个圆环首尾相连 B. Does not constitute a end-to-end]

3. Time Selection range settings (the selected time is over the range will be window prompts), the minute interval set

4. Multi-language settings

5. Time format settings to meet the YYYY/MM/DD hh:mm of this kind of setting rules

6.UE close to iOS native effect

7. Expansion is not only a choice of time, can be passed into the custom linkage selection data

This is mainly about the implementation of the infinite wheel
Data Preparation 1

Here, let me explain.

Get a clever way of how many days in one months.

 Daylist () {/
       * get currentmonthlenght */let
        currentmonthlength = new Date (this.tmpyear, This.tmpmonth + 1, 0). GE Tdate ();
       /* Get Currentmonth Day *
        /Let daylist = Array.from ({length:currentmonthlength}, (value, index) => {
          Dex + 1
        });
        Return Daylist
      },

Here I use the Vue computed method to implement, put into yearList monthList daylist hourList minuteList to store the basic data, here the data is ready to come to a start.

Static effect implementation

There are many ways to implement the roller static effect

1. Visual 3D effect [Add shadow]

2. Actual 3D effect [Css3d]

我把实现效果大致分为上面2种,具体的大家可以自己搜索相关资料,这里展开涉及太多就带过好了

I realized it myself. The second one uses the Css3d

Description

First of all, we see that the selection effect of the original iOS is different between the selection and the wheel outside the range of selection.

So in order to achieve this effect difference I choose to use 2 DOM structure to implement, a DOM implementation wheel, a DOM to achieve black selection effect, so linkage when there is similar to the original effect of the difference

picker-panel A variety of options dom, here only gives the day's, box-day loading the date of the outermost box, to check-line achieve the selected 2 lines, day-list the outermost black effect data, day-wheel gray roller part

<div class= "Picker-panel" >
<!--other box-->
<div class= "Box-day" >
  <div class= " Check-line "></div>
  <div class=" day-checked ">
    <div class=" day-list ">
      <div class= "List-div" v-for= "Day in Renderlistday" >
       {{day.value}}}
      </div>
    </div>
  </div>
  <div class= "Day-wheel" >
    <div class= "Wheel-div" v-for= "Day in Renderlistday" Transform:rotate3d (1, 0, 0, 80deg) translate3d (0px, 0px, 2.5rem);>
    {{day.value}}
    </div>
  < /div>
</div>
<!--other box-->
</div>
. 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-div{
     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
    }
   }

CSS properties that are primarily involved

transform-style: preserve-3d;

Show 3D effect,

-webkit-backface-visibility: hidden;

Auto Hide behind the wheel

postition:absolute;

To locate the wheel.

transform: rotate3d(1, 0, 0, 80deg) translate3d(0px, 0px, 2.5rem);

The angle of each data rotation and the radius of the wheel side view Circle

The angle and construction principle of each data rotation

As pictured above

Is the effect of our roller-stereo diagram, R is our TRANSLATED3D (0px,0px,2.5rem) This CSS in the 2.5rem,

Without this CSS, all data will converge in the center

The image above does not rotate (red represents the data effect we see)

The image above does the rotation (red orange represents the data effect we see)

The blue arc represents the same angle (this involves the knowledge of the angle), also is the visual rotation angle, is the Rotate3d this CSS inside 80deg, I do is each interval 20 degrees, so actually we only use rotates the X axis to rotate the center angle in passing, thus the entire ring to spread out. A full circle can hold 360/20 data, and we can see the positive data, so over a certain angle in the back should not be seen by us, and-webkit-backface-visibility:hidden, this sentence has played a role.

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

Similar to the following figure effect

So we have a second data preparation.

Data Preparation 2

We also use our daylist as the initial data [1,2,3,4,....., 30,31]

Here we take 19 data each time as rendering data, and we need renderlistday initial rendering is [23,24,25,26,27,28,29,30,31,1,2,3,4,5,6,7,8,9,10]

Because this takes the middle number just as the first one (only at the time of initialization)

Renderlistday () {let
        list = [];
        for (let k = This.spin.day.head k <= this.spin.day.last; k++) {let
          obj = {
            value:this.getData (k, ' Day '), 
   
    index:k,
          };
          List.push (obj)
        } return
        list
      },
   

The method of fetching the data is less than 0 inverted to fetch more than 0, the index is larger than the original data length is calculated to get the normal range of the corresponding index, so the above spin is our data fork (initially from 9 to 9)

GetData (idx, type) {
       //...
        else if (type = = ' Day ') {return
          this.daylist[idx% this.dayList.length >= 0? idx% THIS.DAYLIST.LENGTH:IDX% t His.dayList.length + this.dayList.length];
        } 
        //...
      },

Angle of rotation of each data (upper semicircle is positive, bottom semicircle is negative)

<div class= "Wheel-div" v-for= "Day in Renderlistday" v-bind:data-index= "Day.index" "v-bind:style=" {transform: ' Rotate3d (1, 0, 0, ' + (-day.index) *20%360+ ' deg) translate3d (0px, 0px, 2.5rem) '} ' >{{day.value}}{{day.value}}</div >

Then we need to rotate to the angle we need, with our initialization time alignment, This.orday-this.daylist[0] is to get the offset to correct the angle

this. $el. Getelementsbyclassname (' Day-wheel ') [0].style.transform = ' Rotate3d (1, 0, 0, ' + (This.orday-this.daylist[0]) * + ' deg ';

Add Touch Events

The rest is fine. The corresponding Dom binding event is converted to the rotation angle and the check-list displacement according to the distance of the touchmove here Translatey is used to record the actual moving distance, and the final output needs to be counted into the offset

<div class= "Box-day" v-on:touchstart= mytouch ($event, ' Day ') "v-on:touchmove=" Mymove ($event, ' Day ') v-on: Touchend= "Myend ($event, ' Day ')" >
  <div class= "Check-line" ></div>
  <div class= "day-checked ">
    <div class=" day-list "data-translatey=" 0 "style=" Transform:translatey (0rem) ">
      <div class=" List-div "v-for=" Day in Renderlistday "v-bind:data-index=" Day.index ">
        {{day.value}}}
      </div>
    </div>
  </div>
  <div class= "Day-wheel" style= "Transform:rotate3d (1, 0, 0,0deg)" >
    < Div class= "Wheel-div" v-for= "Day in Renderlistday" v-bind:data-index= "Day.index" v-bind:style= "{transform: ' Rotate3d" ( 1, 0, 0, ' + (-day.index) *20%360+ ' deg) translate3d (0px, 0px, 2.5rem) '} ' >
     {day.value}}}
    </div>
  </div>
</div>

Inertia scrolling

This implementation I was using a cubic-bezier (0.19, 1, 0.22, 1)

The judgment gesture is not flicker if it is flicker through an instantaneous velocity to calculate the displacement, and the time, then the one-time set, and then use transition do inertia rolling,
Normal drag setting 1 seconds

The actual effect is still a little bad, later to improve.

Implementation of other functions

This is not a detailed explanation.

Summarize

Self-adapting to the solution of the hand Amoy

The most difficult part of this implementation of this component is the implementation of infinite scrolling, and the construction of the infinite scrolling rendering data, followed by the implementation of inertial scrolling.

Known Issues

1. Inertia Rolling Imperfect

2. Unlimited scrolling implemented. Non-infinite scrolling is not implemented, is the rendering of data is [1,2,3,4,5,6,7,8,9,10]

3. Now choose the day or month of the month or year, the hour or minute is not optional

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.