-
Notifications
You must be signed in to change notification settings - Fork 5
[项目实战] 手机端iscroll滚动+滚动导航指示 #14
Description
此效果在手机端还是很常见的,话不多说,直接看效果
(很奇怪ios录屏无法支持录手指操作)
native的效果包含了几点
1.顶部日期是可以横向滚动的,
2.点击某个日期,就把点击的置为当前状态,并把下方内容滚动到对应日期。
3.当用户滚动下方内容时,顶部日期会随着滚动自动跳到对应日期置为当前状态
4.顶部日期置为当前状态时,会尝试把当前状态放置在中间位置(处于边角的日期没法去中间就不管了)
5.用户滚动下方内容时,每块日期条都会随着滚动fix在它能移动到的最上边
目前我实现到1,2,3,4。而5这个特性只有native实现起来比较爽,h5实现感觉代价挺大,目前也没有见到过h5的实例
一起来看看h5实现出来的效果
(windows下有个巨好好用录屏工具叫gifcam,可以录到手指,安利一下)
用到的插件
1.iscroll 要滚动肯定iscroll少不了滴
地址 https://github.com/cubiq/iscroll
2.waypoint 这个用来反馈滑动到哪了
地址 http://imakewebthings.com/waypoints/guides/jquery-zepto/
Dom准备好
compile了两部分内容,分别是顶部滚动日期和下方的列表内容
接着就开始加入各种行为事件
//顶部滚动日期
var dateTemplate = $('#dateTemplate').html();
$('#calenderDate').html($.compiler(dateTemplate, {
"data": dateArr
}));
//列表内容
var calenderTemplate = $('#calenderTemplate').html();
$('#daysHolder').html($.compiler(calenderTemplate, {
"data": finalData
}));
//顶部滚动,和点击事件
this.scrollTab('calenderDateHolder', 4.5);
this.addScrollTabEvent();
this.addScrollMonitorEvent();让顶部日期开始滑动起来
scrollTab做的事情是让顶部的日期可以横向滚动,传入2个参数,分别是id和一行展示的列数
首先根据传入的列数和id元素的宽度,计算出每一格的宽度,并设置给每个li元素,
然后把li元素的父层设置一下宽度为li的数量*宽度,实战中发现可能li的宽度是个小数,父层这样计算出来的宽度可能包不住li导致li出现换行
最后使用iscroll让id元素滑动起来,成功后看到dom是这个样子的
li的父层还有一个父层,在init的时候指定id要指定最上层,那么iscroll就会找到id的子层,给他设定style的各种translate属性,层级结构是这样的
setScollerItemWidth: function(id, column) { //设定滑动表格每一列的宽度
if (column === undefined) {
column = 2;
}
var $table = $('#' + id);
var scrollItemWidth = $table.width() / column;
var itemNum = $table.find('li').length;
$table.find('li').css({
width: scrollItemWidth + 'px'
});
$table.find('.calender_date').width(scrollItemWidth * itemNum + 1);
},
scrollTab: function(id, column) { //表格开始滑动
this.setScollerItemWidth(id, column);
this.myScroll = new IScroll('#' + id, {
probeType: 2,
scrollX: true,
scrollY: false,
mouseWheel: true,
eventPassthrough: 'vertical',
preventDefault: true
});
},实现点击日期后让下方内容滚动,和滚动下方内容时日期的实时变化
addScrollTabEvent:function(){
var that=this;
//tab date点击滑动到锚点
$("#calenderDate li").on('tap',function(event) {
$("#calenderDate li").removeClass('on');
$(this).addClass('on');
that.myScroll.scrollToElement($(this)[0], 400, true, true);
var order=$(this).index();
console.log(order);
$('#day'+order)[0].scrollIntoView(true);
window.scrollBy(0, -64);
that.isTaping=true;
setTimeout(function(){
that.isTaping=false;
}, 500);
});
$("#calenderDate li").eq(0).trigger('tap');
},
addScrollMonitorEvent:function(){
var that=this;
$('.single_day').each(function(index, el) {
$('#day'+index).waypoint({
handler: function(direction) {
if(that.isTaping){return;}
$("#calenderDate li").removeClass('on');
$("#calenderDate li").eq(index).addClass('on');
that.myScroll.scrollToElement($("#calenderDate li").eq(index)[0], 400, true, true);
},
offset: '64px'
});
});
},点击日期让此元素滚动到中间用到的是这一句
that.myScroll.scrollToElement($(this)[0], 400, true, true);
参数可去iscroll的api查阅,不多说了,只需注意iscroll用到的是dom元素,不是$元素
让下方元素滚动到顶部位置是这两句
$('#day'+order)[0].scrollIntoView(true);
window.scrollBy(0, -64);
scrollIntoView在各个浏览器都是有实现的,只是加的参数(比如平滑滚动,对齐特性)有兼容性问题
把下方元素拉到顶后,需要往下回退64个像素,这个距离就是顶部日期的高度
下方滚动影响上边日期展示的就用waypoint,每个元素到哪里了都会在handler里给出一个回调,根据这个回调进行操作。
遇到的问题
第一个问题就是点击日期的时候,下方内容滚动,此时内容滚动监测又发现了这个滚动,反回来影响日期的展示,所以这里要引入一个点击锁,当点击日期的时候锁定,500毫秒后放开。而滚动监测在回调行为里第一个就判断是否点击锁定了,如果在锁定中就不往下执行,这样就断了两者的联动影响。
第二个问题是由于顶部日期fix在顶部,切日期下方滚动时,偶尔会出现日期这个区域闪动一下,我理解为ios下的刷新率不够,后加入 -webkit-transform: translateZ(0); transform: translateZ(0) 后问题搞定。
第三个问题是顶部的滚动不利索,像是卡住了一样,然后翻看iscroll的demo,发现关键点在touch-action:none; 这个加入后,就可以避免原生的手势操作,iscroll的滑动就丝般顺滑了,文档在此
https://developer.mozilla.org/zh-CN/docs/Web/CSS/touch-action
第四个问题是解决了第三个问题后出现的,注意看顶部bar左边部分,下边的内容已经透出来了

解决办法就是多增加一层结构
于此同时css也要相应处理





