zoukankan      html  css  js  c++  java
  • iscroll源码学习(1)

    iscroll是移端端开发的两大利器之一(另一个是fastclick),为了将它整合的avalon,需要对它认真学习一番。下面是我的笔记。

    第一天看的是它的工具类util.js

    //用于做函数节流
    var rAF = window.requestAnimationFrame	||
    	window.webkitRequestAnimationFrame	||
    	window.mozRequestAnimationFrame		||
    	window.oRequestAnimationFrame		||
    	window.msRequestAnimationFrame		||
    	function (callback) { window.setTimeout(callback, 1000 / 60); };
    
    var utils = (function () {
    	var me = {};
    
    	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.prefixPointerEvent = function (pointerEvent) {
    		return window.MSPointerEvent ? 
    			'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10):
    			pointerEvent;
    	};
            //用来计算加速度,力回馈什么的
    	me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
                     //current为当前位置, start为开始位置, distance就是开始走了多少距离, 
    
    		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
    		};
    	};
            //取得可以用transform样式名
    	var _transform = _prefixStyle('transform');
    
    	me.extend(me, {
    		hasTransform: _transform !== false,//判定浏览器是否支持CSS3 transform
    		hasPerspective: _prefixStyle('perspective') in _elementStyle,//支持透视效果
    		hasTouch: 'ontouchstart' in window,//是否是触摸屏
    		hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed
    		hasTransition: _prefixStyle('transition') in _elementStyle//支持CSS3渐变
    	});
    
    	// This should find all Android browsers lower than build 535.19 (both stock browser and webview) 
            //判定安卓的浏览器是否版本过低
    	me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome/d/.test(window.navigator.appVersion));
    
    	me.extend(me.style = {}, {//修正与CSS3变渐相关的样式名
    		transform: _transform,
    		transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
    		transitionDuration: _prefixStyle('transitionDuration'),
    		transitionDelay: _prefixStyle('transitionDelay'),
    		transformOrigin: _prefixStyle('transformOrigin')
    	});
            //操作类名的三个常用方法
    	me.hasClass = function (e, c) {
    		var re = new RegExp("(^|\s)" + c + "(\s|$)");
    		return re.test(e.className);
    	};
    
    	me.addClass = function (e, c) {
    		if ( me.hasClass(e, c) ) {
    			return;
    		}
    
    		var newclass = e.className.split(' ');
    		newclass.push(c);
    		e.className = newclass.join(' ');
    	};
    
    	me.removeClass = function (e, c) {
    		if ( !me.hasClass(e, c) ) {
    			return;
    		}
    
    		var re = new RegExp("(^|\s)" + c + "(\s|$)", 'g');
    		e.className = e.className.replace(re, ' ');
    	};
    
    	me.offset = function (el) {
    		var left = -el.offsetLeft,
    			top = -el.offsetTop;
    
    		// jshint -W084
    		while (el = el.offsetParent) {
    			left -= el.offsetLeft;
    			top -= el.offsetTop;
    		}
    		// jshint +W084
    
    		return {
    			left: left,
    			top: top
    		};
    	};
    
    	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,
    
    		mousedown: 2,
    		mousemove: 2,
    		mouseup: 2,
    
    		pointerdown: 3,
    		pointermove: 3,
    		pointerup: 3,
    
    		MSPointerDown: 3,
    		MSPointerMove: 3,
    		MSPointerUp: 3
    	});
            //各种缓动公式
    	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)',	// Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 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 );
    			}
    		}
    	});
            //触发tap事件,这是为了低消移动端点击事件有300ms延迟发明出来的自定义事件
    	me.tap = function (e, eventName) {
    		var ev = document.createEvent('Event');
    		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;
    
    		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;
    })();
    

    源码还算易读,但也遇到几个不懂的地方。一个是momentum方法,物理公式忘光了,另一个是offset方法。offset的结果与我们常用的不一致。

    <!DOCTYPE html>
    <html>
        <head>
            <title>iscroll学习 by 司徒正美</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <script src="avalon.js" ></script>
            <script>
    
                window.onload = function() {
                    var elem = document.querySelector("#son")
                    var offset = function(el) {
                        var left = -el.offsetLeft,
                                top = -el.offsetTop;
    
                        // jshint -W084
                        while (el = el.offsetParent) {
                            left -= el.offsetLeft;
                            top -= el.offsetTop;
                        }
                        // jshint +W084
    
                        return {
                            left: left,
                            top: top
                        };
                    };
                    console.log(offset(elem)) //iscroll.offset 返回 [-400,-400]
                    console.log(avalon(elem).offset()) //jQuery.offset, avalon.offset返回 [400, 400]
                   
                }
    
    
            </script>
        </head>
        <body>
            <style>
              
                #parent{
                    position: absolute;
                    top:200px;
                    left:200px;
                }
                #son {
                    position: absolute;
                    top:200px;
                    left:200px;
                }
            </style>
            <div ms-controller="test">
                <div  id="parent" >
                    <input id="son"  />ddd   
                </div
    
            </div>
        </body>
    </html>
    
  • 相关阅读:
    手机端网页web开发要点
    js javascript:void(0) 真正含义
    牛客第二场 C.message(计算几何+二分)
    计算几何_三维凸包
    【kuangbin专题】计算几何_半平面交
    【kuangbin专题】计算几何_凸包
    【kuangbin专题】计算几何基础
    Codeforces 1058 D. Vasya and Triangle(分解因子)
    网络流模板
    2018 Multi-University Training Contest 6
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/3927730.html
Copyright © 2011-2022 走看看