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.