效果如图(日期可左右滑动)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 } }