删减版iScroll

来源:互联网 发布:不动产数据库标准 编辑:程序博客网 时间:2024/06/11 22:52

删减版iScroll

在移动端想使用iScroll,奈何偏大,大的部分功能用不上,因此删减了部分代码,怕名称冲突,随便起了个名字Pan,其中防止重复调用,使用了xPath,贴上代码。

只是删了些东西,所以叫删减版,大部分功能保留。

define(function() {    var instanceMap = {};    var utils = (function() {        var me = {};        me.offset = function(el) {            var left = -el.offsetLeft,                top = -el.offsetTop;            while (el = el.offsetParent) {                left -= el.offsetLeft;                top -= el.offsetTop;            }            return {                left: left,                top: top            };        };        var _elementStyle = document.createElement('div').style;        var _vendor = (function() {            var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],                transform,                i = 0,                l = vendors.length;            for (; i < l; i++) {                transform = vendors[i] + 'ransform';                if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);            }            return false;        })();        function _prefixStyle(style) {            if (_vendor === false) return false;            if (_vendor === '') return style;            return _vendor + style.charAt(0).toUpperCase() + style.substr(1);        }        me.getTime = Date.now || function getTime() {            return new Date().getTime();        };        me.extend = function(target, obj) {            for (var i in obj) {                target[i] = obj[i];            }        };        me.addEvent = function(el, type, fn, capture) {            el.addEventListener(type, fn, !!capture);        };        me.removeEvent = function(el, type, fn, capture) {            el.removeEventListener(type, fn, !!capture);        };        me.momentum = function(current, start, time, lowerMargin, wrapperSize, deceleration) {            var distance = current - start,                speed = Math.abs(distance) / time,                destination,                duration;            deceleration = deceleration === undefined ? 0.0006 : deceleration;            destination = current + (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);            duration = speed / deceleration;            if (destination < lowerMargin) {                destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;                distance = Math.abs(destination - current);                duration = distance / speed;            } else if (destination > 0) {                destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;                distance = Math.abs(current) + destination;                duration = distance / speed;            }            return {                destination: Math.round(destination),                duration: duration            };        };        var _transform = _prefixStyle('transform');        me.extend(me.style = {}, {            transform: _transform,            transitionTimingFunction: _prefixStyle('transitionTimingFunction'),            transitionDuration: _prefixStyle('transitionDuration'),            transitionDelay: _prefixStyle('transitionDelay'),            transformOrigin: _prefixStyle('transformOrigin')        });        me.preventDefaultException = function(el, exceptions) {            for (var i in exceptions) {                if (exceptions[i].test(el[i])) {                    return true;                }            }            return false;        };        me.extend(me.eventType = {}, {            touchstart: 1,            touchmove: 1,            touchend: 1,        });        me.extend(me.ease = {}, {            quadratic: {                style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',                fn: function(k) {                    return k * (2 - k);                }            },            circular: {                style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',                fn: function(k) {                    return Math.sqrt(1 - (--k * k));                }            },            back: {                style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',                fn: function(k) {                    var b = 4;                    return (k = k - 1) * k * ((b + 1) * k + b) + 1;                }            },            bounce: {                style: '',                fn: function(k) {                    if ((k /= 1) < (1 / 2.75)) {                        return 7.5625 * k * k;                    } else if (k < (2 / 2.75)) {                        return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;                    } else if (k < (2.5 / 2.75)) {                        return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;                    } else {                        return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;                    }                }            },            elastic: {                style: '',                fn: function(k) {                    var f = 0.22,                        e = 0.4;                    if (k === 0) {                        return 0;                    }                    if (k == 1) {                        return 1;                    }                    return (e * Math.pow(2, -10 * k) * Math.sin((k - f / 4) * (2 * Math.PI) / f) + 1);                }            }        });        me.click = function(e) {            var target = e.target,                ev;            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);                ev._constructed = true;                target.dispatchEvent(ev);            }        };        return me;    })();    function Pan(el, options) {        this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;        var panId = this.wrapper.getAttribute("data-panid");        //判断实例是否已经存在,存在返回        if (panId && instanceMap[panId]) {            var panInstance = instanceMap[panId];            if (panInstance.wrapper === this.wrapper) {                return panInstance;            } else {                delete instanceMap[panId];            }        }        panId = utils.getTime();        this.wrapper.setAttribute("data-panid", panId);        instanceMap[panId] = this;        this.scroller = this.wrapper.children[0];        this.scrollerStyle = this.scroller.style;        this.options = {            startY: 0,            momentum: true,            bindToWrapper: true,            bounce: true,            bounceTime: 600,            bounceEasing: '',            preventDefault: true,            preventDefaultException: {                tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/            },        };        for (var i in options) {            this.options[i] = options[i];        }        this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;        this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;        this.y = 0;        this._events = {};        this._init();        this.refresh();        this.scrollTo(this.options.startY);        this.enable();    }    Pan.prototype = {        _init: function() {            this._initEvents();        },        destroy: function() {            this._initEvents(true);        },        _transitionEnd: function(e) {            if (e.target != this.scroller || !this.isInTransition) {                return;            }            this._transitionTime();            if (!this.resetPosition(this.options.bounceTime)) {                this.isInTransition = false;            }        },        _start: function(e) {            this.refresh();            if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {                return;            }            if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {                e.preventDefault();            }            var point = e.touches ? e.touches[0] : e,                pos;            this.initiated = utils.eventType[e.type];            this.moved = false;            this.distY = 0;            this._transitionTime();            this.startTime = utils.getTime();            if (this.options.useTransition && this.isInTransition) {                this.isInTransition = false;                pos = this.getComputedPosition();                this._translate(Math.round(pos.y));            } else if (!this.options.useTransition && this.isAnimating) {                this.isAnimating = false;            }            this.startY = this.y;            this.absStartY = this.y;            this.pointY = point.pageY;        },        _move: function(e) {            if (!this.enabled || utils.eventType[e.type] !== this.initiated) {                return;            }            if (this.options.preventDefault) {                e.preventDefault();            }            var point = e.touches ? e.touches[0] : e,                deltaY = point.pageY - this.pointY,                timestamp = utils.getTime(),                newY,                absDistY;            this.pointY = point.pageY;            this.distY += deltaY;            absDistY = Math.abs(this.distY);            if (timestamp - this.endTime > 300 && (absDistY < 10)) {                return;            }            newY = this.y + deltaY;            //newy >0 为超出上边界;newY < this.maxScrollY为超出下边界            if (newY > 0 || newY < this.maxScrollY) {                newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;            }            this.moved = true;            this._translate(newY);            if (timestamp - this.startTime > 300) {                this.startTime = timestamp;                this.startY = this.y;            }        },        _end: function(e) {            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,                momentumY,                duration = utils.getTime() - this.startTime,                newY = Math.round(this.y),                distanceY = Math.abs(newY - this.startY),                time = 0,                easing = '';            this.isInTransition = 0;            this.initiated = 0;            this.endTime = utils.getTime();            //处理当滑动到边界时,回弹动作            if (this.resetPosition(this.options.bounceTime)) {                return;            }            this.scrollTo(newY);            //当touchend触发时,如果中间没有移动,则程序触发click事件到target上            if (!this.moved) {                if (this.options.click) {                    utils.click(e);                }                return;            }            //当快速的滑动时,添加惯性效果(根据滑动的时间,已滑动的距离,保持当前的速度滑动一段距离才停下来)            if (this.options.momentum && duration < 300) {                momentumY = utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration);                newY = momentumY.destination;                time = momentumY.duration;                this.isInTransition = 1;            }            if (newY != this.y) {                if (newY > 0 || newY < this.maxScrollY) {                    easing = utils.ease.quadratic;                }                this.scrollTo(newY, time, easing);                return;            }        },        _resize: function() {            var that = this;            clearTimeout(this.resizeTimeout);            this.resizeTimeout = setTimeout(function() {                that.refresh();            }, this.options.resizePolling);        },        resetPosition: function(time) {            var y = this.y;            time = time || 0;            if (this.y > 0) {                y = 0;            } else if (this.y < this.maxScrollY) {                y = this.maxScrollY;            }            if (y == this.y) {                return false;            }            this.scrollTo(y, time, this.options.bounceEasing);            return true;        },        disable: function() {            this.enabled = false;        },        enable: function() {            this.enabled = true;        },        refresh: function() {            var rf = this.wrapper.offsetHeight;            this.wrapperHeight = this.wrapper.clientHeight;            this.scrollerHeight = this.scroller.offsetHeight;            this.maxScrollY = this.wrapperHeight - this.scrollerHeight;            if (this.maxScrollY > 0) {                this.maxScrollY = 0;            }            this.endTime = 0;            this.wrapperOffset = utils.offset(this.wrapper);            this.resetPosition();        },        scrollTo: function(y, time, easing) {            easing = easing || utils.ease.circular;            this.isInTransition = time > 0;            this._transitionTimingFunction(easing.style);            this._transitionTime(time);            this._translate(y);        },        scrollToElement: function(el, time, offsetY, easing) {            el = el.nodeType ? el : this.scroller.querySelector(el);            if (!el) {                return;            }            var pos = utils.offset(el);            pos.top -= this.wrapperOffset.top;            if (offsetY === true) {                offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);            }            pos.top -= offsetY || 0;            pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;            time = time === undefined || time === null || time === 'auto' ? Math.abs(this.y - pos.top) : time;            this.scrollTo(pos.top, time, easing);        },        _transitionTime: function(time) {            time = time || 0;            this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';        },        _transitionTimingFunction: function(easing) {            this.scrollerStyle[utils.style.transitionTimingFunction] = easing;        },        _translate: function(y) {            this.scrollerStyle[utils.style.transform] = 'translate3d(0px,' + y + 'px, 0px)';            this.y = y;        },        _initEvents: function(remove) {            var eventType = remove ? utils.removeEvent : utils.addEvent,                target = this.options.bindToWrapper ? this.wrapper : window;            eventType(window, 'orientationchange', this);            eventType(window, 'resize', this);            if (this.options.click) {                eventType(this.wrapper, 'click', this, true);            }            eventType(this.wrapper, 'touchstart', this);            eventType(target, 'touchmove', this);            eventType(target, 'touchcancel', this);            eventType(target, 'touchend', this);            eventType(this.scroller, 'transitionend', this);            eventType(this.scroller, 'webkitTransitionEnd', this);        },        getComputedPosition: function() {            var matrix = window.getComputedStyle(this.scroller, null);            matrix = matrix[utils.style.transform].split(')')[0].split(', ');            var x = +(matrix[12] || matrix[4]);            var y = +(matrix[13] || matrix[5]);            return {                x: x,                y: y            };        },        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':                case 'webkitTransitionEnd':                    this._transitionEnd(e);                    break;            }        }    };    Pan.utils = utils;    return Pan;});
0 0
原创粉丝点击