leaflet开源地图库源码阅读笔记(三)——浏览器&移动设备判断(browser.js)(by vczero)

一、源码结构

继上一篇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: !!retina
59     };
60
61 }());

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 lowercase

webkit = 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 the pointerEnabled property has been deprecated in the W3C Pointer Events specification, the recommended way to detect pointer event support is to check for the PointerEvent interface:

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 3d
opera3d = ‘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机制、事件处理、工具类、地理对象模型、地图投影、基本地图对象构建....

时间: 2024-08-23 12:54:36

leaflet开源地图库源码阅读笔记(三)——浏览器&移动设备判断(browser.js)(by vczero)的相关文章

leaflet开源地图库源码阅读笔记(一)——简介&Demo初体验(by vczero)

一.简介 电子地图已经在O2O.生活服务.出行等领域布局,传统的GIS也孕育着互联网基因.传统GIS的图商有ESRI(Arc系列).四维.高德.超图.中地等等.在web互联网领域,百度和高德较为出色.但是开放源代码都远远做的不够,相比而言国外开源较多且丰富,最近认真研读了openlayers2/3和leaflet的源码,收获颇多,不仅加强对浏览器兼容性.HTML5.CSS3等基础,还增强了GIS的基础.本人现在也在一家互联网公司做js api的研发,因此,需要不断地吸取开源代码的营养. leaf

leaflet开源地图库源码研读(四)——OOP的基础构建(by vczero)

一.贴源码 源码存放的目录是src->core->Class.js 1 L.Class = function () {}; 2 3 L.Class.extend = function (props) { 4 5 // extended class with the new prototype 6 var NewClass = function () { 7 8 // call the constructor 9 if (this.initialize) { 10 this.initialize

leaflet开源地图库源码 浏览器&移动设备判断(browser.js)备份

<script> var isIe = !-[1,]; // alert('ie9 之前'+isIe); var ie = 'ActiveXObject' in window; //alert('sadsd'+ie); var ie2 = !!('ActiveXObject' in window); //alert('22222'+ie2); var ie3= !!window.ActiveXObject || !!("ActiveXObject" in window);

leaflet开源地图库源码研读(五)——extend、Object.create、fn.bind分析(Util.js文件)

一.extend:扩展对象的属性 1 var Util = { 2 extend: function (dest) { 3 var i, j, len, src; 4 for (j = 1, len = arguments.length; j < len; j++) { 5 src = arguments[j]; 6 for (i in src) { 7 dest[i] = src[i]; 8 } 9 } 10 return dest; 11 } 12 } 可以,看出extend方法里有2个fo

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中