はじめに
私は過去数か月間 VUE を検討し、ネイティブ js+vue のみを使用していくつかのコンポーネントを実装しようとしました。
PC 時間選択コンポーネント これは、PC 上での時間選択の最初の実装です。モバイル側でも実行されるので、モバイル側での 時間セレクター の実装を共有したいと思います。特殊効果の時間セレクターのアイデアとプロセス。コンポーネント全体は vue-cli
関数に基づいて構築されています
1. 時間選択 [
A.年月日选择
C. 時間と分の選択]
2. スクロールホイール効果 [
B.年月日小时分钟选择
]エンドツーエンド接続]
3. 時間選択範囲設定 (選択した時間が範囲を超える場合、ポップアップウィンドウが表示されます)、分間隔設定
4. 多言語設定5. yyyy/MM/dd HH:mm の要件を満たします ルールを設定します
6. UE はネイティブ iOS エフェクトに近いです
7. 拡張機能は時間を選択するだけでなく、カスタム リンケージ選択データを渡すこともできます
ここでは主に無限スクロール ホイールの実装について話します
データの準備 1ここから入手してください
A.构成一个圆环首尾相连
1 か月の日数を取得する賢い方法。
天
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
monthList
hourList
静的効果の実装スクロールホイールの静的効果を実現するには多くの方法があります
1. 視覚的な3D効果[影を追加]
2. 実際の3D効果[CSS3D]
minuteList
説明まず第一に、スクロールホイールが選択範囲に入った場合と選択範囲外に入った場合では、ネイティブiOSの選択効果が異なることがわかります
それでは、この効果を実現するには違いは、2 つの DOM 構造を使用することにしました。1 つの DOM はスクロール ホイールを実装し、もう 1 つの DOM は黒の選択効果を実装します。そのため、リンクすると、元の
我把实现效果大致分为上面2种,具体的大家可以自己搜索相关资料,这里展开涉及太多就带过好了
picker-panel
box-day
check-line
day-list
を実装します。
day-wheel
<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; } }
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
ビュー円の半径
各データ回転の角度と構築原理
上の写真
は、ローラーの効果の三次元ビューです。rは、私たちのローラーの2.5レムです。 translation3d(0px,0px,2.5rem) css
そのような css がない場合、すべてのデータは円の中心に集められます
上の画像は回転していません (赤色は表示されるデータ効果を表します)
上の図は回転しています (赤とオレンジは、私たちが見ているデータ効果を表しています)
青い円弧で表されている角度は同じです (これには (角度の知識) が含まれます。これは視覚的な回転角度でもあります。 rotate3d CSS の 80deg では、各間隔が 20 度になるようにしています。このようにして、実際には X 軸を回転するだけで、円の中心角も回転するので、リング全体が広がります。完全な円には 360/20 のデータを保持でき、正面のデータは肉眼で見ることができるため、特定の角度を過ぎると、その背後にあるデータは見えなくなります。 -webkit-backface-visibility: hidden;うまくいったという意味です。
postition:absolute;
そこで、2番目のデータ準備があります
データ準備2ここでも、初期データとしてdayListを使用します[1,2,3,4,.. ,30,31]
ここでは、毎回 19 個のデータをレンダリング データとして取得し、renderListDay の初期レンダリングを [23,24,25,26,27,28,29,30,31,1,2] にする必要があります。 ,3 ,4,5,6,7,8,9,10]
真ん中の数字がちょうど最初の数字なので(初期化時のみ)
transform: rotate3d(1, 0, 0, 80deg) translate3d(0px, 0px, 2.5rem);
index が元のデータ長より大きい場合、% 計算を使用して通常の範囲に対応するインデックスを取得します。そのため、上記のスピンはデータをフェッチするためのフォークです (最初は -9 から9)
这里我们发现轮子装不完所有数据,而且我们要实现数据循环
<p class="wheel-p" 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}}</p>
接着需要旋转到我们需要的角度,跟我们的初始化时间对上,this.orDay-this.DayList[0] 是获取偏移量来矫正角度
this.$el.getElementsByClassName('day-wheel')[0].style.transform = 'rotate3d(1, 0, 0, ' + (this.orDay - this.dayList[0]) * 20 + 'deg)';
增加touch事件
剩下的事就很好处理了,给对应的dom绑定事件根据touchmove的距离来转换成旋转的角度 和check-list的位移这里translateY是用来记录实际移动的距离的,最后输出需要算入偏移量
<p class="box-day" v-on:touchstart="myTouch($event,'day')" v-on:touchmove="myMove($event,'day')" v-on:touchend="myEnd($event,'day')"> <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: 'rotate3d(1, 0, 0, '+ (-day.index)*20%360+'deg) translate3d(0px, 0px, 2.5rem)'}"> {{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.现在选择必须 年月日 或者年月日小时分钟 不能单独选小时或者分钟
以上がvue.js は、ネイティブの iOS 時間選択コンポーネントを模倣する開発エクスペリエンスを実装します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。