├── LICENSE ├── README.md ├── leaflet.scalefactor.css ├── leaflet.scalefactor.js ├── leaflet.scalefactor.min.css └── leaflet.scalefactor.min.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # leaflet.ScaleFactor 2 | Display a Scale Factor (e.g. 1:50,000) for Leaflet maps, checkout the [Demo](https://marcchasse.github.io/leaflet.ScaleFactor/). 3 | 4 | Leaflet.ScaleFactor is based on [Leaflet's Control.Scale](http://leafletjs.com/reference.html#control-scale) and works with the latest version of Leaflet, [1.0.0-rc1](http://leafletjs.com/reference-1.0.0.html) it also likely works with older versions. Jquery 1.0 or higher is required for its [`.height()`](http://api.jquery.com/height/) function. A pure JavaScript alternative would be better but i'm not sure how to go about implementing that. 5 | 6 | The calculation to determine the scale factor is approximate and could likely be improved further, as of right now its calculated as follows. 7 | 8 | 1. Find half the map height in pixels (middle of map) 9 | 2. Get Leaflet to determine the lat/long of (0,middle of map) 10 | 3. Get Leaflet to determine the lat/long of (100,middle of map) 11 | 4. Get Leaflet to calculate the real world distance in meters between the two points. 12 | 5. Get the pixels per physical screen millimeter 13 | 1. Add a div with height:1mm; to the page 14 | 2. Get jQuery to return the calculated height in pixels 15 | 6. Multiply 100px by the pixels/mm 16 | 7. Convert physical screen size of 100px from milimeters to meters 17 | 8. Divide real world meters per 100px by screen meters per 100px 18 | 9. Format and display the scale 19 | 20 | 21 | ## Quick Start 22 | 23 | 1. Create a leaflet map. Checkout Leaflets [Quick Start Guide](http://leafletjs.com/examples/quick-start.html) for a basic map example. 24 | 25 | 2. Include jQuery, Leaflet.ScaleFactor.min.css and Leaflet.ScaleFactor.min.js 26 | 27 | ```html 28 | 29 | 30 | 31 | ``` 32 | 3. Add the ScaleFactor control: 33 | ```javascript 34 | L.control.scalefactor().addTo(map); 35 | ``` 36 | ## Complete Example 37 | Here is everything you need to get this up and running. Copy and past the following to an `.html` file: 38 | ```html 39 | 40 | 41 | 42 | 43 | 44 | Leaflet.ScaleFactor DEMO 45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 53 | 54 | 68 | 69 | 70 | ``` 71 | Checkout the [Demo](https://marcchasse.github.io/leaflet.ScaleFactor/) 72 | 73 | ## Options 74 | `L.control.scalefactor` 75 | 76 | | Option | Type | Default | Description | 77 | |----------------|---------|--------------|-------------------------------------------------------------------------------------------------| 78 | | position | String | 'bottomleft' | The position of the control (one of the map corners). See control positions. | 79 | | updateWhenIdle | Boolean | false | If true, the control is updated on moveend, otherwise it's always up-to-date (updated on move). | 80 | -------------------------------------------------------------------------------- /leaflet.scalefactor.css: -------------------------------------------------------------------------------- 1 | .leaflet-control-scalefactor{ 2 | border: 2px solid #777; 3 | line-height: 1.1; 4 | padding: 2px 5px 1px; 5 | font-size: 11px; 6 | white-space: nowrap; 7 | overflow: hidden; 8 | -moz-box-sizing: border-box; 9 | box-sizing: border-box; 10 | 11 | background: #fff; 12 | background: rgba(255, 255, 255, 0.5); 13 | } 14 | 15 | .leaflet-control-scalefactor.leaflet-control{ 16 | margin-left: 5px; 17 | } -------------------------------------------------------------------------------- /leaflet.scalefactor.js: -------------------------------------------------------------------------------- 1 | (function (factory, window) { 2 | 3 | // define an AMD module that relies on 'leaflet' 4 | if (typeof define === 'function' && define.amd) { 5 | define(['leaflet'], factory); 6 | 7 | // define a Common JS module that relies on 'leaflet' 8 | } else if (typeof exports === 'object') { 9 | module.exports = factory(require('leaflet')); 10 | } 11 | 12 | // attach your plugin to the global 'L' variable 13 | if (typeof window !== 'undefined' && window.L) { 14 | window.L.Control.ScaleFactor = factory(L); 15 | L.control.scalefactor = function (options) { 16 | return new window.L.Control.ScaleFactor(options); 17 | }; 18 | } 19 | }(function (L) { 20 | var ScaleFactor = L.Control.extend({ 21 | options: { 22 | position: 'bottomleft', 23 | updateWhenIdle: true 24 | }, 25 | 26 | onAdd: function (map) { 27 | var className = 'leaflet-control-scalefactor', 28 | container = L.DomUtil.create('div', className), 29 | options = this.options; 30 | 31 | this._mScale = L.DomUtil.create('div', className + '-line', container); 32 | 33 | map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); 34 | map.whenReady(this._update, this); 35 | 36 | return container; 37 | }, 38 | 39 | onRemove: function (map) { 40 | map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); 41 | }, 42 | 43 | _pxTOmm: (function () { 44 | var heightRef = document.createElement('div'); 45 | heightRef.style = 'height:1mm;display:none'; 46 | heightRef.id = 'heightRef'; 47 | document.body.appendChild(heightRef); 48 | 49 | heightRef = document.getElementById('heightRef'); 50 | var pxPermm = $('#heightRef').height(); 51 | 52 | heightRef.parentNode.removeChild(heightRef); 53 | 54 | return function pxTOmm(px) { 55 | return px / pxPermm; 56 | } 57 | })(), 58 | 59 | _update: function () { 60 | var map = this._map; 61 | 62 | var CenterOfMap = map.getSize().y / 2; 63 | 64 | var RealWorlMetersPer100Pixels = map.distance( 65 | map.containerPointToLatLng([0, CenterOfMap]), 66 | map.containerPointToLatLng([100, CenterOfMap]) 67 | ); 68 | 69 | var ScreenMetersPer100Pixels = this._pxTOmm(100) / 1000; 70 | 71 | var scaleFactor = RealWorlMetersPer100Pixels / ScreenMetersPer100Pixels; 72 | 73 | //.replace formats the scale with commas 50000 -> 50,000 74 | this._mScale.innerHTML = '1:' + Math.round(scaleFactor).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 75 | } 76 | 77 | }); 78 | 79 | return ScaleFactor; 80 | }, window)); -------------------------------------------------------------------------------- /leaflet.scalefactor.min.css: -------------------------------------------------------------------------------- 1 | .leaflet-control-scalefactor{border:2px solid #777;line-height:1.1;padding:2px 5px 1px;font-size:11px;white-space:nowrap;overflow:hidden;-moz-box-sizing:border-box;box-sizing:border-box;background:#fff;background:rgba(255,255,255,.5)}.leaflet-control-scalefactor.leaflet-control{margin-left:5px} -------------------------------------------------------------------------------- /leaflet.scalefactor.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"function"==typeof define&&define.amd?define(["leaflet"],e):"object"==typeof exports&&(module.exports=e(require("leaflet"))),void 0!==t&&t.L&&(t.L.Control.ScaleFactor=e(L),L.control.scalefactor=function(e){return new t.L.Control.ScaleFactor(e)})}(function(e){var t=e.Control.extend({options:{position:"bottomleft",updateWhenIdle:!0},onAdd:function(t){var n="leaflet-control-scalefactor",o=e.DomUtil.create("div",n),i=this.options 2 | return this._mScale=e.DomUtil.create("div",n+"-line",o),t.on(i.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),o},onRemove:function(e){e.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_pxTOmm:function(){var e=document.createElement("div") 3 | e.style="height:1mm;display:none",e.id="heightRef",document.body.appendChild(e),e=document.getElementById("heightRef") 4 | var t=$("#heightRef").height() 5 | return e.parentNode.removeChild(e),function(e){return e/t}}(),_update:function(){var e=this._map,t=e.getSize().y/2,n=e.distance(e.containerPointToLatLng([0,t]),e.containerPointToLatLng([100,t])),o=this._pxTOmm(100)/1e3,i=n/o 6 | this._mScale.innerHTML="1:"+(""+Math.round(i)).replace(/\B(?=(\d{3})+(?!\d))/g,",")}}) 7 | return t},window) --------------------------------------------------------------------------------