leaflet.scale.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * L.Control.Scale is used for displaying metric/imperial scale on the map.
  3. */
  4. L.Control.Scale = L.Control.extend({
  5. options: {
  6. position: 'bottomleft',
  7. maxWidth: 100,
  8. metric: false,
  9. imperial: true,
  10. updateWhenIdle: false,
  11. offset:[10,10]
  12. },
  13. initialize: function (options) {
  14. L.setOptions(this, options);
  15. },
  16. onAdd: function (map) {
  17. this._map = map;
  18. var className = 'leaflet-control-scale',
  19. container = L.DomUtil.create('div', className),
  20. options = this.options;
  21. switch(this.options.position){
  22. case 'topleft':
  23. container.style.marginLeft = this.options.offset[0]+'px';
  24. container.style.marginTop = this.options.offset[1]+'px';
  25. break;
  26. case 'topright':
  27. container.style.marginRight = this.options.offset[0]+'px';
  28. container.style.marginTop = this.options.offset[1]+'px';
  29. break;
  30. case 'bottomleft':
  31. container.style.marginLeft = this.options.offset[0]+'px';
  32. container.style.marginBottom = this.options.offset[1]+'px';
  33. break;
  34. case 'bottomright':
  35. container.style.marginRight = this.options.offset[0]+'px';
  36. container.style.marginBottom = this.options.offset[1]+'px';
  37. break;
  38. }
  39. this._addScales(options, className, container);
  40. map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
  41. map.whenReady(this._update, this);
  42. L.DomEvent.on(container,'contextmenu',L.DomEvent.stopPropagation);
  43. return container;
  44. },
  45. onRemove: function (map) {
  46. map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
  47. },
  48. getUnit:function(){
  49. return this.options.metric?'metric':'imperial'
  50. },
  51. setUnit:function(unit){
  52. if(unit == 'metric'){
  53. this.options.metric = true;
  54. this.options.imperial = false;
  55. this._mScale.style.display = 'block';
  56. this._iScale.style.display = 'none';
  57. }
  58. if(unit == 'imperial'){
  59. this.options.metric = false;
  60. this.options.imperial = true;
  61. this._iScale.style.display = 'block';
  62. this._mScale.style.display = 'none';
  63. }
  64. this._update();
  65. },
  66. _addScales: function (options, className, container) {
  67. this._mScale = L.DomUtil.create('div', className + '-line', container);
  68. this._iScale = L.DomUtil.create('div', className + '-line', container);
  69. if (options.metric) {
  70. this._mScale.style.display = 'block';
  71. this._iScale.style.display = 'none';
  72. }
  73. if (options.imperial) {
  74. this._iScale.style.display = 'block';
  75. this._mScale.style.display = 'none';
  76. }
  77. },
  78. _update: function () {
  79. var bounds = this._map.getBounds(),
  80. centerLat = bounds.getCenter().lat,
  81. halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180),
  82. dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180,
  83. size = this._map.getSize(),
  84. options = this.options,
  85. maxMeters = 0;
  86. if (size.x > 0) {
  87. maxMeters = dist * (options.maxWidth / size.x);
  88. }
  89. this._updateScales(options, maxMeters);
  90. },
  91. _updateScales: function (options, maxMeters) {
  92. if (options.metric && maxMeters) {
  93. this._updateMetric(maxMeters);
  94. }
  95. if (options.imperial && maxMeters) {
  96. this._updateImperial(maxMeters);
  97. }
  98. },
  99. _updateMetric: function (maxMeters) {
  100. var meters = this._getRoundNum(maxMeters);
  101. this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px';
  102. this._mScale.innerHTML = meters < 1000 ? '<span>'+meters + ' 米</span>' : '<span>'+(meters / 1000) + ' 公里</span>';
  103. },
  104. _updateImperial: function (maxMeters) {
  105. var maxFeet = maxMeters * 3.2808399,
  106. scale = this._iScale,
  107. maxMiles, miles, feet;
  108. feet = this._getRoundNum(maxFeet);
  109. scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px';
  110. scale.innerHTML = '<span>'+feet + ' 英尺</span>';
  111. },
  112. _getScaleWidth: function (ratio) {
  113. return Math.round(this.options.maxWidth * ratio) - 10;
  114. },
  115. _getRoundNum: function (num) {
  116. var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
  117. d = num / pow10;
  118. d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1;
  119. return pow10 * d;
  120. }
  121. });
  122. L.Map.addInitHook(function () {
  123. if (this.options.scaleControl) {
  124. this.scaleControl = new L.Control.Scale();
  125. this.addControl(this.scaleControl);
  126. }
  127. });
  128. L.control.scale = function (options) {
  129. return new L.Control.Scale(options);
  130. };
  131. /**
  132. * 添加比例尺控件
  133. * @param {[type]} options [description]
  134. * @return {[type]} [description]
  135. */
  136. map2DViewer.setScaleControl = function(options) {
  137. var defaultData = {
  138. action: 'add',
  139. position: 'bottomleft',
  140. offset: [10, 10]
  141. }
  142. _.merge(defaultData, options);
  143. switch (defaultData.action) {
  144. case 'add':
  145. this.scaleControl = new L.Control.Scale({
  146. position: defaultData.position,
  147. offset: defaultData.offset,
  148. metric: defaultData.metric,
  149. imperial: defaultData.imperial,
  150. }).addTo(this.map);
  151. return this.scaleControl;
  152. break;
  153. case 'remove':
  154. this.map.removeControl(this.scaleControl)
  155. break;
  156. }
  157. }