Skip to content

[项目实战] 手机端iscroll滚动+滚动导航指示 #14

@mask2012

Description

@mask2012

此效果在手机端还是很常见的,话不多说,直接看效果

(很奇怪ios录屏无法支持录手指操作)

native-scroll

native的效果包含了几点

1.顶部日期是可以横向滚动的,
2.点击某个日期,就把点击的置为当前状态,并把下方内容滚动到对应日期。
3.当用户滚动下方内容时,顶部日期会随着滚动自动跳到对应日期置为当前状态
4.顶部日期置为当前状态时,会尝试把当前状态放置在中间位置(处于边角的日期没法去中间就不管了)
5.用户滚动下方内容时,每块日期条都会随着滚动fix在它能移动到的最上边

目前我实现到1,2,3,4。而5这个特性只有native实现起来比较爽,h5实现感觉代价挺大,目前也没有见到过h5的实例

一起来看看h5实现出来的效果

(windows下有个巨好好用录屏工具叫gifcam,可以录到手指,安利一下)

h5-scroll2

用到的插件

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是这个样子的

image

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左边部分,下边的内容已经透出来了
image

解决办法就是多增加一层结构

image

于此同时css也要相应处理

image

最后就完美解决,如图,同时我也把顶部bar增加了一个底部border,更好地区分。
image

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions