概述
L.Browser
是一个包含静态属性的命名空间,用于Leaflet内部进行浏览器/功能检测。
源码实现
L.Browser
是在core
模块中的Browser.js
中实现的,其源码实现如下:
var style = document.documentElement.style;
// ### 1.浏览器内核/类型检测
// IE检测
var ie = "ActiveXObject" in window; //IE 浏览器特有属性
var ielt9 = ie && !document.addEventListener; // IE9 以下版本不支持addEventListener
var edge = "msLaunchUri" in navigator && "documentMode" in document; // Edge浏览器
// WebKit 内核 (Chrome /Safari / 新版Opera)
var webkit = userAgentContains("webkit");
var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10);
// Android 设备检测
var android = userAgentContains("android");
var android23 =userAgentContains('android 2') || userAgentContains('android 3'); // Android 2.x /3.x
var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);
//其它浏览器
var opera = !!window.opera; // Opera
var chrome = !edge && userAgentContains('chrome'); // Chrome(排除Edge)
var gecko = userAgentContains('gecko') && !webkit && !opera && !ie; // Firefox /Gecko
var safari = !chrome && userAgentContains('safari'); // Safari(排除Chrome)
var phantom = userAgentContains('phantom'); // PhantomJS
// ### 2. CSS特性检测
var opera12 = 'OTransition' in style; // Opera 12以及更早版本
var ie3d = ie && ('transition' in style); // IE是否支持CSS3过渡属性
var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23; // Webkit 是否支持3D变换
var gecko3d = 'MozPerspective' in style; //Firefox是否支持3D变换
var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom; //综合判断是否支持3D
// ### 3.设备/操作系统检测
var win = navigator.platform.indexOf('Win') === 0; //Windows系统
var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile'); //移动设备(手机/平板)
var mobileWebkit = mobile && webkit;//移动端 WebKit 浏览器
var mobileWebkit3d = mobile && webkit3d; //移动端 支持3D 的Webkit浏览器
var mobileOpera = mobile && opera; //移动端 Opera
var mobileGecko = mobile && gecko; //移动端Firefox
var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1; //Retina屏幕
var mac = navigator.platform.indexOf('Mac') === 0; // macOS系统
var linux = navigator.platform.indexOf('Linux') === 0; //Linux系统
// ### 4.指针/触摸输入事件检测
var msPointer = !window.PointerEvent && window.MSPointerEvent; // 旧版IE/Edge的Pointer事件
var pointer = !!(window.PointerEvent || msPointer); //是否支持Pointer 事件
var touchNative = 'ontouchstart' in window || !!window.TouchEvent; //原生触控支持
var touch = !window.L_NO_TOUCH && (touchNative || pointer); //是否启用触控(排除手动禁用 L_NO_TOUCH)
// ### 5. 图形技术支持检测
// Canvas 支持
var canvas = (function () {
return !!document.createElement('canvas').getContext;
}());
// SVG支持
var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect);
var inlineSvg = !!svg && (function () {
var div = document.createElement('div');
div.innerHTML = '<svg/>';
return (div.firstChild && div.firstChild.namespaceURI) === 'http://www.w3.org/2000/svg';
})();
// VML 支持(IE8-)
var vml = !svg && (function () {
try {
var div = document.createElement('div');
div.innerHTML = '<v:shape adj="1"/>';
var shape = div.firstChild;
shape.style.behavior = 'url(#default#VML)';
return shape && (typeof shape.adj === 'object');
} catch (e) {
return false;
}
}());
// ### 6. 高级事件优化检测
var passiveEvents = (function () {
var supportsPassiveOption = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function () { // eslint-disable-line getter-return
supportsPassiveOption = true;
}
});
window.addEventListener('testPassiveEventSupport', Util.falseFn, opts);
window.removeEventListener('testPassiveEventSupport', Util.falseFn, opts);
} catch (e) {
// Errors can safely be ignored since this is only a browser support test.
}
return supportsPassiveOption;
}());
// ### 7. 辅助函数
function userAgentContains(str) {
return navigator.userAgent.toLowerCase().indexOf(str) >= 0;
}
export default {
ie: ie,
ielt9: ielt9,
edge: edge,
webkit: webkit,
android: android,
android23: android23,
androidStock: androidStock,
opera: opera,
chrome: chrome,
gecko: gecko,
safari: safari,
phantom: phantom,
opera12: opera12,
win: win,
ie3d: ie3d,
webkit3d: webkit3d,
gecko3d: gecko3d,
any3d: any3d,
mobile: mobile,
mobileWebkit: mobileWebkit,
mobileWebkit3d: mobileWebkit3d,
msPointer: msPointer,
pointer: pointer,
touch: touch,
touchNative: touchNative,
mobileOpera: mobileOpera,
mobileGecko: mobileGecko,
retina: retina,
passiveEvents: passiveEvents,
canvas: canvas,
svg: svg,
vml: vml,
inlineSvg: inlineSvg,
mac: mac,
linux: linux
};
总结
这段代码的目的是通过 特性检测(而非 User Agent
嗅探)来识别浏览器类型、设备特性和功能支持,并将结果存储在 L.Browser 的静态属性中。例如:
L.Browser.ie
表示是否是 IE 浏览器。L.Browser.touch
表示是否支持触控操作。L.Browser.canvas
表示是否支持Canvas
。
Leaflet 利用这些信息在不同浏览器中自动选择最佳实现(如使用 SVG
、Canvas
或 VML
渲染地图),并优化交互行为(如触控、3D 变换)