效果如圖(日期可左右滑動)web
思路:
一、先獲得相鄰三個周的數據,初始化的時候容器向左移動一個視口的距離,確保中間周在可視範圍(在可視範圍的索引爲1)
二、觸摸移動階段,好比向左移動,至關於改變但是範圍的索引,也就是2,即向左移動過兩個視口的範圍
三、移動結束,這時右邊已經沒有待顯示的數據,須要重組數據,再向後加一週,使當前顯示的周在中間,同時須要改變顯示的索引爲1數組
在當前視口內顯示本週的7天,因爲須要滑動,因此事先還須要把今天之前的一週和之後的一週準備好dom
let today = moment().format('YYYY-MM-DD') // 當前日期:"2018-09-14" moment(today).subtract(7, 'd').format('YYYY-MM-DD') // 上一週的今天:"2018-09-07" moment(today).add(7, 'd').format('YYYY-MM-DD') // 下一週的今天:"2018-09-21"
獲得數組: dateside
由此數據能夠生成三個模板,分別表示上週,本週和下週,再根據此數據,計算上週,本週和下週的詳情。動畫
getDays: function (day) { let arr = [] /* 計算傳進來的日期爲星期幾 */ let weekOfDate = Number(moment(day).format('E')) // 提早定義好的: this.week = ['一', '二', '三', '四', '五', '六', '日'] for (let i = 0; i < this.week.length; i++) { arr.push( { date: moment(day).subtract(weekOfDate - i - 1, 'd').format('YYYY-MM-DD'), week: this.week[i] } ) } return arr }
遍歷數組dates。分別傳進getDays可的到三週的詳情this
而後遍歷數組進行頁面渲染spa
<template v-for="(item, index) in dates"> <div class="slider"> <div class="day" v-for="(day, dayIndex) in getDays(item.date)"> <div :class="{today: day.date === defaultDate}">{{day.date.split('-')[2]}}</div> </div> </div> </template>
這裏,靜態顯示已經完成3d
改寫上方的頁面渲染代碼code
<div class="week-slider"> <div class="sliders" ref="sliders" @touchstart="touchStart" @touchmove="touchmove" // 初始樣式,應該向飾釦左方移動一個視口的距離,確保當前周在中間 :style="getTransform" @touchend="touchend" @webkit-transition-end="transitionEnd" @transitionend="transitionEnd"> <template v-for="(item, index) in dates"> <div class="slider"> <div class="day" v-for="(day, dayIndex) in getDays(item.date)"> <div :class="{today: day.date === defaultDate}">{{day.date.split('-')[2]}}</div> </div> </div> </template> </div> </div>
// actIndex: 當前活動視圖的縮影,初始爲1,sliderWidth:視口的寬度, distan: {x:0, y: 0}: 觸摸移動的距離 // getTransform: function () { this.endx = (-this.actIndex * this.sliderWidth) + this.distan.x let style = {} style['transform'] = 'translateX(' + this.endx + 'px)' // 這一條必須寫,由於觸摸移動的時候須要過渡動畫,可是在動畫結束重組數據的時候須要瞬間回到該去的位置,不能要過渡動畫 style['transition'] = this.isAnimation ? 'transform .5s ease-out' : 'none' return style }
最後觸摸時間處理:orm
touchStart: function (e) { this.start.x = e.touches[0].pageX }, touchmove: function (e) { // 這裏須要過渡動畫 this.isAnimation = true this.distan.x = e.touches[0].pageX - this.start.x // 須要移動的容器 let dom = this.$refs.sliders // 向左 this.endx = this.endx + this.distan.x dom.style['transform'] = 'translateX('+ this.endx + 'px)' }, touchend: function (e) { this.isAnimation = true this.distan.x = e.changedTouches[0].pageX - this.start.x // 向右 if (this.distan.x > 0) { this.direction = 'right' this.actIndex = 0 } else if (this.distan.x < 0) { this.direction = 'left' this.actIndex = 2 } this.distan.x = 0 },
過渡結束後重置容器位置
// 過渡結束 transitionEnd: function () { this.isAnimation = false if (this.actIndex === 2) { this.dates.push({ date: moment(this.dates[this.actIndex].date).add(7, 'd').format('YYYY-MM-DD') }) this.dates.shift() this.actIndex = 1 }else if (this.actIndex === 0) { this.dates.unshift({ date: moment(this.dates[this.actIndex].date).subtract(7, 'd').format('YYYY-MM-DD') }) this.dates.pop() this.actIndex = 1 } }