一、源码结构
继上一篇blog说到整个leaflet的结构,这里重新贴一张图(src -> core),直观点,如下图。这篇blog主要研读core文件夹的源码Brower.js。因为怕篇幅较大,所以Class.js,Events.js,Handler.js,Util.js后续开博。他们是整个框架的backbone(脊梁),也是最为基础的部分。
二、Browser.js:浏览器兼容的基础构建者
引LeafLet:L.Browser handles different browser and feature detections for internal Leaflet use.
上源码,源码太长,这里折叠起来,具体的如下:
1 (function () { 2 3 var ua = navigator.userAgent.toLowerCase(), 4 doc = document.documentElement, 5 6 ie = 'ActiveXObject' in window, 7 8 webkit = ua.indexOf('webkit') !== -1, 9 phantomjs = ua.indexOf('phantom') !== -1,10 android23 = ua.search('android [23]') !== -1,11 Chrome = ua.indexOf('chrome') !== -1,12 13 mobile = typeof orientation !== 'undefined',14 msPointer = navigator.msPointerEnabled && navigator.msMaxTouchPoints && !window.PointerEvent,15 pointer = (window.PointerEvent && navigator.pointerEnabled && navigator.maxTouchPoints) || msPointer,16 17 ie3d = ie && ('transition' in doc.style),18 webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23,19 gecko3d = 'MozPerspective' in doc.style,20 Opera3d = 'OTransition' in doc.style;21 22 23 var retina = 'devicePixelRatio' in window && window.devicePixelRatio > 1;24 25 if (!retina && 'matchMedia' in window) {26 var matches = window.matchMedia('(min-resolution:144dpi)');27 retina = matches && matches.matches;28 }29 30 var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window ||31 (window.DocumentTouch && document instanceof window.DocumentTouch));32 33 L.Browser = {34 ie: ie,35 ielt9: ie && !document.addEventListener,36 webkit: webkit,37 gecko: (ua.indexOf('gecko') !== -1) && !webkit && !window.opera && !ie,38 android: ua.indexOf('android') !== -1,39 android23: android23,40 chrome: chrome,41 safari: !chrome && ua.indexOf('safari') !== -1,42 43 ie3d: ie3d,44 webkit3d: webkit3d,45 gecko3d: gecko3d,46 opera3d: opera3d,47 any3d: !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs,48 49 mobile: mobile,50 mobileWebkit: mobile && webkit,51 mobileWebkit3d: mobile && webkit3d,52 mobileOpera: mobile && window.opera,53 54 touch: !!touch,55 msPointer: !!msPointer,56 pointer: !!pointer,57 58 retina: !!retina59 };60 61 }());View Code
Browser.js做的一件事就是甄别用户使用的浏览器类型,这里其实有一大堆的述说,因为是研读LeafLet的源码,因此,从Browser.js的源码说起。一般做浏览器基础判断的方法为UA判断(但是,好多浏览器不争气喜欢伪装,like chrome,like webkit...)、属性特性判断、渲染引擎判断。
var ua = navigator.userAgent.toLowerCase(); //window.navigator.userAgent,使用浏览器的UA判断,这里全部转为小写。如下图,在chrome中的判断。
var ie = 'ActiveXObject' in window;//相当于!!window['ActiveXObject'],判断全局window对象是否具有ActiveXObject,如果有,则是IE类型的浏览器。如下图在chrome下判断。
var ua = navigator.userAgent.toLowerCase(), // user agent lowercasewebkit = ua.indexOf('webkit') !== -1, // 是否是webkit的内核phantomjs = ua.indexOf('phantom') !== -1, //是否是phantomJS渲染的引擎内核,类似于Node.js的服务端js,可用于抓包、预渲染、页面快照等等android23 = ua.search('android [23]') !== -1, //是否是移动端android的2.3以上版本chrome = ua.indexOf('chrome') !== -1; // 是否是chrome内核mobile = typeof orientation !== 'undefined', //是否可以横屏旋转,判断是否是移动设备
msPointer = navigator.msPointerEnabled && navigator.msMaxTouchPoints && !window.PointerEvent;
navigator.msPointerEnabled判断浏览器是否支持MSPointer的事件,navigator.msMaxTouchPoints判断用户的设备支持多点触摸;window.PointerEvent判断是否支持触发指针事件。关于window.PointerEvent,上面有写:请注意,指针事件功能检测不能作为判断设备本身是否支持触控或笔输入的指标。PointerEvent属性只检查该平台是否会触发指针事件,无论系统中存在何种硬件。要测试触控功能和多点触控支持,请使用maxTouchPoints属性。Because thepointerEnabledPRoperty has been deprecated in the W3C Pointer Events specification, the recommended way to detect pointer event support is to check for thePointerEventinterface:
if(window.PointerEvent) { o.addEventListener("pointerdown", handler); } else if(window.MSPointerEvent) { o.addEventListener("MSPointerDown", handler); }
因此有:pointer = (window.PointerEvent && navigator.pointerEnabled && navigator.maxTouchPoints) || msPointer;获取指针的类型。
doc = document.documentElement,ie3d = ie && ('transition' in doc.style), //IE中关于3D的标准webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, //webkit的CSS3支持gecko3d = 'MozPerspective' in doc.style, //mozilla 3dopera3d = 'OTransition' in doc.style; // opera 3d
这里,来看看,document.documentElement.style,表示支持css的属性。
var retina = 'devicePixelRatio' in window && window.devicePixelRatio > 1;//设备像素比,有需要了解的话,可以看看这篇文章:设备像素比devicePixelRatio简单介绍。
关于视窗的媒体查询如下代码,如果需要了解相关扩展内容,可以访问这里:Mozilla wiki。
if (!retina && 'matchMedia' in window) {var matches = window.matchMedia('(min-resolution:144dpi)');retina = matches && matches.matches;}
触摸设备的验证:
var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch));
三、浏览器综合判断
贴上源码,一看便知了。
L.Browser = { ie: ie, ielt9: ie && !document.addEventListener, webkit: webkit, gecko: (ua.indexOf('gecko') !== -1) && !webkit && !window.opera && !ie, android: ua.indexOf('android') !== -1, android23: android23, chrome: chrome, safari: !chrome && ua.indexOf('safari') !== -1, ie3d: ie3d, webkit3d: webkit3d, gecko3d: gecko3d, opera3d: opera3d, any3d: !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs, mobile: mobile, mobileWebkit: mobile && webkit, mobileWebkit3d: mobile && webkit3d, mobileOpera: mobile && window.opera, touch: !!touch, msPointer: !!msPointer, pointer: !!pointer, retina: !!retina };
四、总结
(1)前端的API需要兼容很多版本的浏览器,那么浏览器的判断始终是不可避免的,没有哪一种判断可以尽善尽美,我们一般从需求出发。
(2)准备这边blog研读整个core的源码,但是怕篇幅太长,决定多些几篇。
(3)阅读源码扩展了自己的知识,读书系统,读源码扩展边界体系。
(4)后面几篇:关于面向对象的Class研读、Events机制、事件处理、工具类、地理对象模型、地图投影、基本地图对象构建....
附:
第一篇:leaflet简单介绍&Demo
第二篇:leaflet源码整体框架
新闻热点
疑难解答