何时使用 L.TileLayer 与 L.tileLayer

cpa*_*tor 3 javascript leaflet

我刚刚使用 Leaflet 为网站构建地图,并注意到要添加图块图层,至少可以使用两种方法L.TileLayer()L.tileLayer(),它们的名称仅在单个字符的大小写上有所不同。

然而,虽然这两个方法返回的对象都可以添加到由L.map()返回的对象返回的地图对象中,但返回的对象L.TileLayer()似乎没有该addTo()方法,而返回的对象似乎没有该方法L.tileLayer()。例如两者

var map = L.map('map');
var tiles = new L.TileLayer(<tileUrl>, {attribution: <tileAttrib>});
map.addLayer(tiles);
Run Code Online (Sandbox Code Playgroud)

var map = L.map('map');
var tiles = new L.tileLayer(<tileUrl>, {attribution: <tileAttrib>});
map.addLayer(tiles);
Run Code Online (Sandbox Code Playgroud)

var map = L.map('map');
L.tileLayer(<tileUrl>, {attribution: <tileAttrib>}).addTo(map);
Run Code Online (Sandbox Code Playgroud)

同时

var map = L.map('map');
L.TileLayer(<tileUrl>, {attribution: <tileAttrib>}).addTo(map);
Run Code Online (Sandbox Code Playgroud)

失败。浏览Leaflet的文档,似乎正确的使用方法是,L.tileLayer()那么问题是有什么用L.TileLayer()

这是到目前为止我的代码的完整示例,要尝试不同的替代方案,只需取消注释要测试的代码并确保其他替代方案得到注释

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
        
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
      <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
      
      <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.3/dist/leaflet.css"
            integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
            crossorigin=""/>
      <script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js"
            integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q=="
            crossorigin=""> </script>
   </head>
   <body onload="makeMap()">
      <script type="text/javascript">
         function makeMap() {
            var tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
            var tileAttrib = 'Map data &copy <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'; 
            var map = L.map('map').setView([63,15],9);
            
            // using tileLayer and addLayer - this works
            var tiles = new L.tileLayer(tileUrl, {attribution: tileAttrib});
            map.addLayer(tiles);
            
            // using tileLayer and addTo - this works
//             L.tileLayer(tileUrl, {attribution: tileAttrib}).addTo(map);
            
            // using TileLayer and addLayer - this works
//             var tiles = new L.TileLayer(tileUrl, {attribution: tileAttrib});
//             map.addLayer(tiles);
            
            // using TileLayer and addTo - this fails
//             L.TileLayer(tileUrl, {attribution: tileAttrib}).addTo(map);
         }
         
      </script>
      <table border=1 style="position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 100%; height: 100%;">
         <tr style="height: 100%;">
            <td>
               <div id="map" style="width: 100%; height: 100%;"></div>
            </td>
         </tr>
      </table>
   </body>
</html>
Run Code Online (Sandbox Code Playgroud)

Iva*_*hez 5

长话短说:

这两个都是有效且等效的:

var foo = L.tileLayer(arguments);
var foo = new L.TileLayer(arguments);
Run Code Online (Sandbox Code Playgroud)

这两个在语法上是有效的(因为 Javascript 的历史包袱),但最终会导致错误:

var foo = new L.tileLayer(arguments);
var foo = L.TileLayer(arguments);
Run Code Online (Sandbox Code Playgroud)

要添加瓦片层,至少可以使用两种方法,L.TileLayer()以及L.tileLayer()

嗯,它们并不是真正的两种方法。从技术上讲,L.TileLayer是 的实例Object,并且L.tileLayer是 的实例Function,它继承了 的原型Object。并L充当命名空间而不是类实例。

你看,Javascript 中的面向对象编程很奇怪。您可以将new关键字与几乎任何具有原型的对象一起使用。对于大多数精通“正确”OOP 的人来说,基于原型的继承是令人困惑的。

如今,有了 ES2015 标准和花哨的class关键字,这实际上并不是一个问题(我想说这是一个问题,但隐藏在语法糖层之下)。但在过去,开发人员不得不诉诸类继承的创造性解决方案,这有时会涉及到原型链的混乱

Leaflet 使用了这些方法的组合 - 作为一个不希望的副作用L.TileLayer它变成了Function一个可以L.TileLayer()直接调用的方法,这非常令人困惑。

Leaflet 还使用了工厂函数的概念:返回类实例的函数。引用其中一份传单教程

大多数Leaflet 类都有相应的工厂函数。工厂函数与类具有相同的名称,但用 inlowerCamelCase代替UpperCamelCase

function myBoxClass(name, options) {
    return new MyBoxClass(name, options);
}
Run Code Online (Sandbox Code Playgroud)

这只是为了方便:它使用户免于new在那个令人恐惧的时代再次new键入关键字

但这会产生另一个不需要的副作用,因为在 Javascript 中,所有Functions 都有一个原型,这意味着你可以做类似的事情

 function myFunction() { ... }
 var wtf = new myFunction();
Run Code Online (Sandbox Code Playgroud)

因此,new L.tileLayer()也是有效的语法(但在运行时失败)。


那有什么用呢L.TileLayer()

再次强调,L.TileLayer()作为函数调用是一个不希望有的副作用。但L.TileLayer代表一个类,并且对其进行引用很重要,因为以下原因:

 if (layer instanceof L.TileLayer)
Run Code Online (Sandbox Code Playgroud)