iscroll源码实现原理(三)

_end方法

        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
            return;
        }

        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
            e.preventDefault();
        }

        //获取手指离开的点
        var point = e.changedTouches ? e.changedTouches[0] : e,
            momentumX,
            momentumY,
            //duration是当前拖动的时间,move时候每300ms变了一次
            duration = utils.getTime() - this.startTime,
            newX = Math.round(this.x),
            newY = Math.round(this.y),
            distanceX = Math.abs(newX - this.startX),
            distanceY = Math.abs(newY - this.startY),
            time = 0,
            easing = '';

        this.isInTransition = 0;
        this.initiated = 0;
        this.endTime = utils.getTime();

        // reset if we are outside of the boundaries
        //记录我们是不是已经离开了边界了,如果离开边界了就不会执行后面逻辑,而直接重置DOM位置
        if ( this.resetPosition(this.options.bounceTime) ) {
            return;
        }

        this.scrollTo(newX, newY);  // ensures that the last position is rounded

        // we scrolled less than 10 pixels
        //如果最后放手的时候没有滚动,类似与我们是点击,它这里可以触发tap事件或者click,建议用tap
        if ( !this.moved ) {

            if ( this.options.tap ) {
                utils.tap(e, this.options.tap);
            }

            if ( this.options.click ) {
                utils.click(e);
            }

            this._execEvent('scrollCancel');
            return;
        }

        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
            this._execEvent('flick');
            return;
        }

        // start momentum animation if needed
        //计算动能
        if ( this.options.momentum && duration < 300 ) {
            momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };
            momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };
            newX = momentumX.destination;
            newY = momentumY.destination;
            time = Math.max(momentumX.duration, momentumY.duration);
            this.isInTransition = 1;
        }

// INSERT POINT: _end

        if ( newX != this.x || newY != this.y ) {
            // 如果越界会调整ease函数
            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
                easing = utils.ease.quadratic;
            }

            this.scrollTo(newX, newY, time, easing);
            return;
        }

        this._execEvent('scrollEnd');

resetPosition方法

他是记录我们是不是已经离开了边界了,如果离开边界了就不会执行后面逻辑,而直接重置DOM位置

var x = this.x,  
            y = this.y;

        time = time || 0;

        if ( !this.hasHorizontalScroll || this.x > 0 ) {
            x = 0;
        } else if ( this.x < this.maxScrollX ) {
            x = this.maxScrollX;
        }

        if ( !this.hasVerticalScroll || this.y > 0 ) {
            y = 0;
        } else if ( this.y < this.maxScrollY ) {
            y = this.maxScrollY;
        }

        if ( x == this.x && y == this.y ) {
            return false;
        }

        this.scrollTo(x, y, time, this.options.bounceEasing);

        return true;

scrollTo方法

传入距离与时间后,会移动到对应位置,并且判断是使用css动画还是降级

scrollTo: function (x, y, time, easing) {  
        easing = easing || utils.ease.circular;

        this.isInTransition = this.options.useTransition && time > 0;

        if ( !time || (this.options.useTransition && easing.style) ) {
            this._transitionTimingFunction(easing.style);
            this._transitionTime(time);
            this._translate(x, y);
        } else {
            this._animate(x, y, time, easing.fn);
        }
}

iscroll提供的调用方法

  • destory 是用来销毁你实例化的iScroll 实例,包括之前绑定的所有iscroll 事件。

  • reresh 这个方法非常有用,当你的滚动区域的内容发生改变 或是 滚动区域不正确,都用通过调用refresh 来使得iscroll 重新计算滚动的区域,包括滚动条,来使得iscroll 适合当前的dom。

  • scrollTo 这个方法接受4个参数 x, y, time, relative x 为移动的x轴坐标,y为移动的y轴坐标, time为移动时间,relative表示是否相对当前位置。

  • scrollToElement 这个方法实际上是对scrollTo的进一步封装,接受两个参数(el,time),el为需要滚动到的元素引用,time为滚动时间。

  • disable 调用这个方法会立即停止动画滚动,并且把滚动位置还原成0,取消绑定touchmove, touchend、touchcancel事件。

  • enable 调用这个方法,使得iscroll恢复默认正常状态

由此,主要的部分解析完了,这里只是说明了最核心的代码,因为对于h5开发,更关心的是touch事件等,iscroll5还支持鼠标的处理,元素对齐,键盘和滚动的处理等,有兴趣的可以自行阅读