zoukankan      html  css  js  c++  java
  • iscroll源码初涉

      最近尝试做web app时候,用上了神器iScroll,鉴于功力尚浅,并没有完全用好神器,所以今天特意来认真学习!

      翻开官网,目前的版本是5,但是相关的文章并不多,具体的文件版本是:

    • iscroll.js 常规版本
    • iscroll-lite.js 阉割版本,如果只需要滑动功能,推荐这个,体积很小。不支持snap,scrollbars,mouse wheel,key bindings。
    • iscroll-probe.js 专门提供获取当前位置的功能,未来可能在常规版本中加入。
    • iscroll-zoom.js 添加zooming功能
    • iscroll-infinlte.js 由于过长的列表滚动对手机设备硬件要求较高,所以此版本利用缓存机制来达到这效果。

      项目里面用的是iscroll-probe这个版本,具体原因是需要使用定位功能,但是今天学习,还是选软柿子(iscroll-lite)来捏吧。

      进门第一段代码:

    //请求动画帧
    var rAF = window.requestAnimationFrame   ||
        window.webkitRequestAnimationFrame   ||
        window.mozRequestAnimationFrame      ||
        window.oRequestAnimationFrame        ||
        window.msRequestAnimationFrame       ||
        function (callback) { window.setTimeout(callback, 1000 / 60); };
    /*
    显示器16.7ms刷新间隔之前发生了其他绘制请求(setTimeout),导致所有帧丢失,setTimeout的定时器值推荐最小使用16.7ms的原因(16.7 = 1000 / 60, 即每秒60帧)
    requestAnimationFrame与setTimeout的不同在于,前者跟着浏览器重绘时间走,不存在后者丢帧的问题
    */

      

       完全不懂……于是马上找鑫爷的博客翻看才知这是一个js的动画接口----请求动画帧,requestAnimationFrame与setTimeout的不同在于,前者跟着浏览器重绘时间走,不存在后者丢帧的问题。《CSS3动画那么强,requestAnimationFrame还有毛线用?》。 

      大概初窥到iScroll的滑动效果的大门,继续往下看,结构非常清晰:util + iscroll + iscroll.prototype。

      util主要是封装了一些获取样式名称(前缀)的方法,事件绑定方法,动画缓动方法,样式操作方法,其中最重要的是 preventDefaultException , tap , click这三个方法。

    // 配合config里面的preventDefaultException属性,匹配到的element使用e.preventDefault()。
    // 默认preventDefaultException是 { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ }
    me.preventDefaultException = function (el, exceptions) {
        for ( var i in exceptions ) {
            if ( exceptions[i].test(el[i]) ) {
                return true;
            }
        }
        return false;
    };
    
    me.tap = function (e, eventName) {
        var ev = document.createEvent('Event');
        /**
        只有在新创建的 Event 对象被 Document 对象或 Element 对象的 dispatchEvent() 方法分派之前,才能调用 Event.initEvent() 方法        
        初始化新事件对象的属性
        */
        ev.initEvent(eventName, true, true);
        ev.pageX = e.pageX;
        ev.pageY = e.pageY;
        //事件触发器就是用来触发某个元素下的某个事件
        e.target.dispatchEvent(ev);
    };
    
    me.click = function (e) {
        var target = e.target,
            ev;
    //不是select/input/textarea就创建事件
    if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { ev = document.createEvent('MouseEvents'); ev.initMouseEvent('click', true, true, e.view, 1, target.screenX, target.screenY, target.clientX, target.clientY,e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,0, null);    //作为是否需要perventDefault的标志   ev._constructed = true; target.dispatchEvent(ev); } };

       继续往下,就是iScroll的初始化操作,new iScroll的时候,会优先处理一些默认设置,其中有如下几点需要注意:

    1. eventPassthrough参数支持两种写法,一是boolean类型true / false , 二是string类型'vertical' / 'horizontal';
    2. eventPassthrough设为true时候,会自动转为'vertical',并且会设置scrollX为false,即水平滑动的时候,使用的是浏览器原生滑动;
    3. freeScroll只能与scrollX一起使用 {scrollX:true,freeScroll:true}

      最后就是

    // IScroll初始化鼠标/手势事件
    this._init();
    // 设置可滑动值
    this.refresh();
    // 定位到最顶最左
    this.scrollTo(this.options.startX, this.options.startY);
    // 代表“启用”的一个标志
    this.enable();

      此中最重要的是_init方法里面调用的_initEvents, 使用的是handleEvent。 利用这个特性可以把任意对象注册为事件处理程序,只要它拥有 handleEvent 方法。

    所以iScroll里面有一个handleEvent属性,利用element.addEventListener( 'transitionend', IScroll)的方式,来处理相关事件。

    IScroll.prototype = {
      handleEvent: function (e) {
          switch ( e.type ) {
                case 'touchstart':
                    ......
                    this._start(e);
                    break;
                case 'touchmove':
                    ......
                    this._move(e);
                    break;
                case 'touchend':
                    ......
                    this._end(e);
                    break;
                case 'orientationchange':
                case 'resize':
                    this._resize();
                    break;
                case 'transitionend':
                    ......
                    this._transitionEnd(e);
                    break;
                case 'wheel':
                    ......
                    this._wheel(e);
                    break;
                case 'keydown':
                    this._key(e);
                    break;
                case 'click':
                    if ( !e._constructed ) {
                        e.preventDefault();
                        e.stopPropagation();
                    }
                    break;
            }
        }
    }    

         好了,iScroll的初始化以及事件处理已经差不多了,接下来就是事件处理程序,估计也是一些位置处理的东西了吧,继续:

    • _start(e)    具体作用是初始化一些位置信息;
    • _move(e)  移动过程更新位置信息,触发动态效果;
    • _end(e)     结束时根据是否需要缓动而作相应的缓动动作

      具体的可以查看我写的《iscroll-lite源码注释》,其实,看完源码,真的没什么很复杂的,但是有几点觉得有待商榷的:

    1. 对于_execEvent(eventType)的方法,应该再加上当前触发的event对象,_execEvent( eventType,event ),因为在执行的时候this._events[type][i].apply(this, [].slice.call(arguments, 1));会从第二个参数截取,加上event对象,有助于我们判断是在哪个元素上触发事件。
    2. off解绑事件,缺乏一次性解绑的方法,建议把解绑的方法修改如下:
      if ( index > -1 ) {
          this._events[type].splice(index, 1);
      }else{
          this._events[type].length = 0;
      }

      最后送上完整的参数设置:

    var options = {
        startX: 0,
        startY: 0,    
        //Y轴是否滑动
        scrollY: true,
        //X轴是否滑动
        scrollX: true,
        //是否自由滑动 x y都滑 , freeScroll只能与scrollX一起使用 {scrollX:true,freeScroll:true}
        freeScroll : false,
        //方向锁定阈值,比如用户点击屏幕后,x与y之间差距大于5px,判断用户的拖动意图,是x方向拖动还是y方向
        directionLockThreshold: 5,
        //是否有惯性缓冲动画
        momentum: true,
        //超出边界时候是否还能拖动
        bounce: true,
        //超出边界还原时间点
        bounceTime: 600,
        //超出边界返回的动画
        bounceEasing: '',
        //是否阻止默认滚动事件
        preventDefault: true,
        //当遇到表单元素则不阻止冒泡,而是弹出系统自带相应的输入控件
        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },
        //硬件合成 通过GPU做图形渲染
        HWCompositing: true,
        //使用transition
        useTransition: true,
        //使用transform
        useTransform: true,
        //穿透 是否不触发原生滑动
        eventPassthrough : false,
        //缓动函数 {string|function}
        bounceEasing : '',
        //resize时候隔60ms就执行refresh方法重新获取位置信息
        resizePolling : 60,
        //是否允许点击事件
        click : false,
        //模拟tap事件,并且触发addEventListener('tap')所指定的方法
        tap : 'tap',
        //匀减速变量
        deceleration : 0.0006,
        //事件是否绑定到wrapper元素上,否则大部分绑定到window
        bindToWrapper : false.
        //是否禁用鼠标
        disableMouse : false,
        //是否禁用win系统的pointer事件
        disablePointer : false,
        //是否禁用touch事件
        disableTouch : false
    };
  • 相关阅读:
    fiddler抓取java系程序的网络通信
    ZOJ 2724 Windows Message Queue(优先队列)
    FZU 电动车通行证制度
    Havel定理
    Catch That Cow
    Trie树
    zoj 2876 Phone List
    zoj 2420
    getchar
    zoj 1315 Excuses, Excuses!
  • 原文地址:https://www.cnblogs.com/viccici/p/3878680.html
Copyright © 2011-2022 走看看