• 基于Leaflet的leaflet-sidebar侧边栏组件集成


    如果你需要在Leaflet地图中增加一个侧边栏,以此来做一个额外的数据处理,那么您可以使用现成的leaflet-sidebar组件来帮助您加快开发速度,同时,该组件基于leaflet进行了扩展,更加灵活。

    言归正传,本文开始重点阐述如何进行组件的引入和集成。

    第一步、在github上想在组件。

    相应的github地址为:https://github.com/Turbo87/sidebar-v2.git,下载后得到的目录结构大致如下:

    第二步、打开其示例程序

    目录在examples,里面有例子。

    我们可以看到,这个控件不仅支持leaflet,同时支持openlayers。所以非常好用。

    第三步、可以打开position-right.html,这个是官方提供的示例,用于演示侧边栏摆放在右边。使用浏览器打开可以看到如下页面:

    这是官方提供的基于osm底图的演示页面,那么怎么在本地进行集成开发呢?

    第三步、使用本地影像服务进行开发

    复制position-right2.html文件,使用熟悉的方式将底图替换为本地。关键代码如下:

    1. L.CRS.CustomEPSG4326 = L.extend({}, L.CRS.Earth, {
    2. code: 'EPSG:4326',
    3. projection: L.Projection.LonLat,
    4. transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5),
    5. scale: function (zoom) {
    6. return 256 * Math.pow(2, zoom - 1);
    7. }
    8. });
    9. var mymap = L.map('map',{crs:L.CRS.CustomEPSG4326,attributionControl: false}).setView([28.250248, 112.896366], 10);
    10. function onMapClick(e) {
    11. L.popup().setLatLng(e.latlng)
    12. .setContent("坐标为:" + e.latlng.toString())
    13. .openOn(mymap);
    14. }
    15. $(document).ready(function(){
    16. $("#mapid").height(window.screen.height-76 - 65 - 20);
    17. mymap.invalidateSize(true);//地图重绘
    18. //底图
    19. L.tileLayer('http://localhost:8086/data/basemap_nowater/1_10_tms/{z}/{x}/{y}.jpg', {
    20. maxZoom: 20,
    21. minZoom:3,
    22. attribution: 'diy Map data © yelangking contributors, ',
    23. id: 'mapbox/streets-v11',
    24. tileSize: 256,
    25. zoomOffset: -1
    26. }).addTo(mymap);
    27. //标签
    28. L.tileLayer('http://localhost:8086/data/basemap_nowater/1-10label/{z}/{x}/{y}.png', {maxZoom: 10,minZoom:3,
    29. id: 'mapbox/label',tileSize: 256,zoomOffset: -1
    30. }).addTo(mymap);
    31. mymap.on('click', onMapClick);
    32. // add a polygon
    33. var polygon = L.polygon([
    34. [28.31177, 112.80762],
    35. [28.31451, 113.1633],
    36. [28.00415, 113.17566],
    37. [28.00278, 112.81174]
    38. ],{
    39. color: 'green',
    40. fillColor: '#f03',
    41. fillOpacity: 0.5
    42. }).addTo(mymap);
    43. initLayerArray();//初始化地图图层
    44. });

    第四步、引入sidebar的css和js文件

    <link rel="stylesheet" href="../css/leaflet-sidebar.css" />
     <script src="../js/leaflet-sidebar.js"></script>

    第五步、在dom中绑定sidebar到map中

    var sidebar = L.control.sidebar('sidebar', {position: 'right'}).addTo(mymap);

    打开浏览器访问这个地址,可以看到以下的页面:

    经过上述的步骤,就完成了sidebar的继承。完整代码如下:

    1. html>
    2. <html lang="en">
    3. <head>
    4. <title>sidebar-v2 exampletitle>
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    6. <meta charset="utf-8">
    7. <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
    8. <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
    9. <link rel="stylesheet" href="../css/leaflet-sidebar.css" />
    10. <style>
    11. body {
    12. padding: 0;
    13. margin: 0;
    14. }
    15. html, body, #map {
    16. height: 100%;
    17. font: 10pt "Helvetica Neue", Arial, Helvetica, sans-serif;
    18. }
    19. .lorem {
    20. font-style: italic;
    21. color: #AAA;
    22. }
    23. style>
    24. head>
    25. <body>
    26. <div id="sidebar" class="sidebar collapsed">
    27. <div class="sidebar-tabs">
    28. <ul role="tablist">
    29. <li><a href="#home" role="tab" id="xz_info"><i class="fa fa-bars">i>a>li>
    30. <li><a href="#profile" role="tab"><i class="fa fa-user">i>a>li>
    31. <li class="disabled"><a href="#messages" role="tab"><i class="fa fa-envelope">i>a>li>
    32. <li><a href="https://github.com/Turbo87/sidebar-v2" role="tab" target="_blank"><i class="fa fa-github">i>a>li>
    33. ul>
    34. <ul role="tablist">
    35. <li><a href="#settings" role="tab"><i class="fa fa-gear">i>a>li>
    36. ul>
    37. div>
    38. <div class="sidebar-content">
    39. <div class="sidebar-pane" id="home">
    40. <h1 class="sidebar-header">
    41. sidebar-v2
    42. <span class="sidebar-close"><i class="fa fa-caret-right">i>span>
    43. h1>
    44. <p>A responsive sidebar for mapping libraries like <a href="http://leafletjs.com/">Leafleta> or <a href="http://openlayers.org/">OpenLayersa>.p>
    45. <p class="lorem">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.p>
    46. <p class="lorem">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.p>
    47. <p class="lorem">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.p>
    48. div>
    49. <div class="sidebar-pane" id="profile">
    50. <h1 class="sidebar-header">Profile<span class="sidebar-close"><i class="fa fa-caret-right">i>span>h1>
    51. div>
    52. <div class="sidebar-pane" id="messages">
    53. <h1 class="sidebar-header">Messages<span class="sidebar-close"><i class="fa fa-caret-right">i>span>h1>
    54. div>
    55. <div class="sidebar-pane" id="settings">
    56. <h1 class="sidebar-header">Settings<span class="sidebar-close"><i class="fa fa-caret-right">i>span>h1>
    57. div>
    58. div>
    59. div>
    60. <div id="map" class="sidebar-map">div>
    61. <a href="https://github.com/Turbo87/sidebar-v2/"><img style="position: fixed; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub">a>
    62. <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js">script>
    63. <script src="../js/leaflet-sidebar.js">script>
    64. <script src="../../jquery/jquery.js">script>
    65. <script>
    66. L.CRS.CustomEPSG4326 = L.extend({}, L.CRS.Earth, {
    67. code: 'EPSG:4326',
    68. projection: L.Projection.LonLat,
    69. transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5),
    70. scale: function (zoom) {
    71. return 256 * Math.pow(2, zoom - 1);
    72. }
    73. });
    74. var mymap = L.map('map',{crs:L.CRS.CustomEPSG4326,attributionControl: false}).setView([28.250248, 112.896366], 10);
    75. function onMapClick(e) {
    76. L.popup().setLatLng(e.latlng)
    77. .setContent("坐标为:" + e.latlng.toString())
    78. .openOn(mymap);
    79. }
    80. $(document).ready(function(){
    81. $("#mapid").height(window.screen.height-76 - 65 - 20);
    82. mymap.invalidateSize(true);//地图重绘
    83. //底图
    84. L.tileLayer('http://localhost:8086/data/basemap_nowater/1_10_tms/{z}/{x}/{y}.jpg', {
    85. maxZoom: 20,
    86. minZoom:3,
    87. attribution: 'diy Map data © yelangking contributors, ',
    88. id: 'mapbox/streets-v11',
    89. tileSize: 256,
    90. zoomOffset: -1
    91. }).addTo(mymap);
    92. //标签
    93. L.tileLayer('http://localhost:8086/data/basemap_nowater/1-10label/{z}/{x}/{y}.png', {maxZoom: 10,minZoom:3,
    94. id: 'mapbox/label',tileSize: 256,zoomOffset: -1
    95. }).addTo(mymap);
    96. mymap.on('click', onMapClick);
    97. // add a polygon
    98. var polygon = L.polygon([
    99. [28.31177, 112.80762],
    100. [28.31451, 113.1633],
    101. [28.00415, 113.17566],
    102. [28.00278, 112.81174]
    103. ],{
    104. color: 'green',
    105. fillColor: '#f03',
    106. fillOpacity: 0.5
    107. }).addTo(mymap);
    108. initLayerArray();//初始化地图图层
    109. });
    110. var sidebar = L.control.sidebar('sidebar', {position: 'right'}).addTo(mymap);
    111. script>
    112. body>
    113. html>

    有兴趣的朋友可以看一下sidebar.js这个文件,他提供了以下内置的函数,可以方便调用。sidebar.js的源码如下:

    1. /* global L */
    2. /**
    3. * @name Sidebar
    4. * @class L.Control.Sidebar
    5. * @extends L.Control
    6. * @param {string} id - The id of the sidebar element (without the # character)
    7. * @param {Object} [options] - Optional options object
    8. * @param {string} [options.position=left] - Position of the sidebar: 'left' or 'right'
    9. * @see L.control.sidebar
    10. */
    11. L.Control.Sidebar = L.Control.extend(/** @lends L.Control.Sidebar.prototype */ {
    12. includes: (L.Evented.prototype || L.Mixin.Events),
    13. options: {
    14. position: 'left'
    15. },
    16. initialize: function (id, options) {
    17. var i, child;
    18. L.setOptions(this, options);
    19. // Find sidebar HTMLElement
    20. this._sidebar = L.DomUtil.get(id);
    21. // Attach .sidebar-left/right class
    22. L.DomUtil.addClass(this._sidebar, 'sidebar-' + this.options.position);
    23. // Attach touch styling if necessary
    24. if (L.Browser.touch)
    25. L.DomUtil.addClass(this._sidebar, 'leaflet-touch');
    26. // Find sidebar > div.sidebar-content
    27. for (i = this._sidebar.children.length - 1; i >= 0; i--) {
    28. child = this._sidebar.children[i];
    29. if (child.tagName == 'DIV' &&
    30. L.DomUtil.hasClass(child, 'sidebar-content'))
    31. this._container = child;
    32. }
    33. // Find sidebar ul.sidebar-tabs > li, sidebar .sidebar-tabs > ul > li
    34. this._tabitems = this._sidebar.querySelectorAll('ul.sidebar-tabs > li, .sidebar-tabs > ul > li');
    35. for (i = this._tabitems.length - 1; i >= 0; i--) {
    36. this._tabitems[i]._sidebar = this;
    37. }
    38. // Find sidebar > div.sidebar-content > div.sidebar-pane
    39. this._panes = [];
    40. this._closeButtons = [];
    41. for (i = this._container.children.length - 1; i >= 0; i--) {
    42. child = this._container.children[i];
    43. if (child.tagName == 'DIV' &&
    44. L.DomUtil.hasClass(child, 'sidebar-pane')) {
    45. this._panes.push(child);
    46. var closeButtons = child.querySelectorAll('.sidebar-close');
    47. for (var j = 0, len = closeButtons.length; j < len; j++)
    48. this._closeButtons.push(closeButtons[j]);
    49. }
    50. }
    51. },
    52. /**
    53. * Add this sidebar to the specified map.
    54. *
    55. * @param {L.Map} map
    56. * @returns {Sidebar}
    57. */
    58. addTo: function (map) {
    59. var i, child;
    60. this._map = map;
    61. for (i = this._tabitems.length - 1; i >= 0; i--) {
    62. child = this._tabitems[i];
    63. var sub = child.querySelector('a');
    64. if (sub.hasAttribute('href') && sub.getAttribute('href').slice(0,1) == '#') {
    65. L.DomEvent
    66. .on(sub, 'click', L.DomEvent.preventDefault )
    67. .on(sub, 'click', this._onClick, child);
    68. }
    69. }
    70. for (i = this._closeButtons.length - 1; i >= 0; i--) {
    71. child = this._closeButtons[i];
    72. L.DomEvent.on(child, 'click', this._onCloseClick, this);
    73. }
    74. return this;
    75. },
    76. /**
    77. * @deprecated - Please use remove() instead of removeFrom(), as of Leaflet 0.8-dev, the removeFrom() has been replaced with remove()
    78. * Removes this sidebar from the map.
    79. * @param {L.Map} map
    80. * @returns {Sidebar}
    81. */
    82. removeFrom: function(map) {
    83. console.log('removeFrom() has been deprecated, please use remove() instead as support for this function will be ending soon.');
    84. this.remove(map);
    85. },
    86. /**
    87. * Remove this sidebar from the map.
    88. *
    89. * @param {L.Map} map
    90. * @returns {Sidebar}
    91. */
    92. remove: function (map) {
    93. var i, child;
    94. this._map = null;
    95. for (i = this._tabitems.length - 1; i >= 0; i--) {
    96. child = this._tabitems[i];
    97. L.DomEvent.off(child.querySelector('a'), 'click', this._onClick);
    98. }
    99. for (i = this._closeButtons.length - 1; i >= 0; i--) {
    100. child = this._closeButtons[i];
    101. L.DomEvent.off(child, 'click', this._onCloseClick, this);
    102. }
    103. return this;
    104. },
    105. /**
    106. * Open sidebar (if necessary) and show the specified tab.
    107. *
    108. * @param {string} id - The id of the tab to show (without the # character)
    109. */
    110. open: function(id) {
    111. var i, child;
    112. // hide old active contents and show new content
    113. for (i = this._panes.length - 1; i >= 0; i--) {
    114. child = this._panes[i];
    115. if (child.id == id)
    116. L.DomUtil.addClass(child, 'active');
    117. else if (L.DomUtil.hasClass(child, 'active'))
    118. L.DomUtil.removeClass(child, 'active');
    119. }
    120. // remove old active highlights and set new highlight
    121. for (i = this._tabitems.length - 1; i >= 0; i--) {
    122. child = this._tabitems[i];
    123. if (child.querySelector('a').hash == '#' + id)
    124. L.DomUtil.addClass(child, 'active');
    125. else if (L.DomUtil.hasClass(child, 'active'))
    126. L.DomUtil.removeClass(child, 'active');
    127. }
    128. this.fire('content', { id: id });
    129. // open sidebar (if necessary)
    130. if (L.DomUtil.hasClass(this._sidebar, 'collapsed')) {
    131. this.fire('opening');
    132. L.DomUtil.removeClass(this._sidebar, 'collapsed');
    133. }
    134. return this;
    135. },
    136. /**
    137. * Close the sidebar (if necessary).
    138. */
    139. close: function() {
    140. // remove old active highlights
    141. for (var i = this._tabitems.length - 1; i >= 0; i--) {
    142. var child = this._tabitems[i];
    143. if (L.DomUtil.hasClass(child, 'active'))
    144. L.DomUtil.removeClass(child, 'active');
    145. }
    146. // close sidebar
    147. if (!L.DomUtil.hasClass(this._sidebar, 'collapsed')) {
    148. this.fire('closing');
    149. L.DomUtil.addClass(this._sidebar, 'collapsed');
    150. }
    151. return this;
    152. },
    153. /**
    154. * @private
    155. */
    156. _onClick: function() {
    157. if (L.DomUtil.hasClass(this, 'active'))
    158. this._sidebar.close();
    159. else if (!L.DomUtil.hasClass(this, 'disabled'))
    160. this._sidebar.open(this.querySelector('a').hash.slice(1));
    161. },
    162. /**
    163. * @private
    164. */
    165. _onCloseClick: function () {
    166. this.close();
    167. }
    168. });
    169. /**
    170. * Creates a new sidebar.
    171. *
    172. * @example
    173. * var sidebar = L.control.sidebar('sidebar').addTo(map);
    174. *
    175. * @param {string} id - The id of the sidebar element (without the # character)
    176. * @param {Object} [options] - Optional options object
    177. * @param {string} [options.position=left] - Position of the sidebar: 'left' or 'right'
    178. * @returns {Sidebar} A new sidebar instance
    179. */
    180. L.control.sidebar = function (id, options) {
    181. return new L.Control.Sidebar(id, options);
    182. };

    总结:本文介绍了leaflet的侧边栏控制组件sidebar,同时详细说明了如何将sidebar集成到leaflet中。如果有什么疑问,欢迎交流。

  • 相关阅读:
    C++前缀和算法的应用:得到连续 K 个 1 的最少相邻交换次数 原理源码测试用例
    形态学笔记:侵蚀+膨胀+开运算+闭运算+形态学梯度+顶帽运算+黑帽运算
    通过提示工程将化学知识整合到大型语言模型中
    【Android UI】贝塞尔曲线 ④ ( 使用 android.graphics.Path 提供的 cubicTo 方法绘制三阶贝塞尔曲线示例 )
    C语言进阶指针(3) ——qsort的实现
    Deno加入ECMA
    如何试用 Vectorizer.AI 将位图转换为矢量图
    将任意一组非线性增长的数均匀映射至0到1上
    Pytorch框架的学习(4)
    2.2异步编程
  • 原文地址:https://blog.csdn.net/yelangkingwuzuhu/article/details/126514927