/* * Distance plugin for MapBBCode */ if( !('mapBBCodeHandlers' in window) ) window.mapBBCodeHandlers = []; window.mapBBCodeHandlers.push({ applicableTo: function( layer ) { return layer instanceof L.Polyline && !(layer instanceof L.Polygon); }, _updateLength: function( map, layer, newLayer, removing ) { // The hook is stateful. Since there may be multiple maps per ui, // we add measurement control reference to a map. if( map && map._measureControl ) map._measureControl.updateLength(layer, newLayer, removing); }, _bindMeasurement: function( layer ) { layer.options.clickable = true; layer.on('mouseover click', function(e) { // display polyline length this._updateLength(layer._map, layer); }, this); layer.on('mouseout edit', function(e) { // display total length this._updateLength(layer._map); }, this); layer.on('remove', function(e) { // display total length minus polyline length this._updateLength(layer._map, null, layer, true); }, this); }, initDrawControl: function( draw ) { draw.options.draw.polyline.showLength = true; }, createEditorPanel: function( layer ) { this._bindMeasurement(layer); }, objectToLayer: function( layer ) { this._bindMeasurement(layer); // this may mean control.updateBBCode() was called, so update displayed length // though this won't work, because layer._map is null this._updateLength(layer._map, null, layer); }, // add measuring control panelHook: function( control, ui ) { var MC = L.Control.extend({ options: { position: 'bottomleft', button: false, metric: true, prefixTotal: 'Total length', prefixSingle: 'Length of that line' }, initialize: function(control, options) { L.setOptions(this, options); this._control = control; }, onAdd: function(map) { var container = this._container = document.createElement('div'); if( this.options.button ) { container.className = 'leaflet-bar'; container.style.background = 'white'; container.style.padding = '0px 5px'; } else { try { container.style.background = 'rgba(255, 255, 255, 0.8)'; } catch( err ) { // invalid value in IE8 container.style.background = 'white'; } container.style.padding = '0px 5px'; container.style.margin = 0; container.style.fontSize = '11px'; } var stop = L.DomEvent.stopPropagation; L.DomEvent .on(container, 'click', stop) .on(container, 'mousedown', stop) .on(container, 'dblclick', stop); container.style.visibility = 'hidden'; return container; }, updateLength: function( layer, newLayer, removing ) { var len = layer ? this._getLength(layer) : this._getTotalLength(newLayer, removing); if( len < 0.001 ) this._container.style.visibility = 'hidden'; else { this._container.style.visibility = 'visible'; if( this.options.button ) this._container.style.fontWeight = layer ? 'bold' : 'normal'; var prefix = this.options.button ? '' : this.options[layer ? 'prefixSingle' : 'prefixTotal'] + ': '; this._container.innerHTML = prefix + this._readableDistance(len); } }, _getLength: function( layer ) { if( layer instanceof L.Polygon || !(layer instanceof L.Polyline) ) return 0; var i, d = 0, latlngs = layer.getLatLngs(); for( i = 1; i < latlngs.length; i++ ) { d += latlngs[i-1].distanceTo(latlngs[i]); } return d; }, _getTotalLength: function( newLayer, removing ) { var d = 0; this._control.eachLayer(function(layer) { if( !removing || layer != newLayer ) { d += this._getLength(layer); } }, this); if( newLayer && !removing ) d += this._getLength(newLayer); return d; }, _readableDistance: function( distance ) { var precision, suffix, divide = 1; if (this.options.metric) { if (distance > 1100) { divide = 1000; suffix = 'km'; } else { suffix = 'm'; } } else { distance *= 0.3048; if (distance > 2000) { divide = 5280; suffix = 'mi'; } else { suffix = 'ft'; } } distance /= divide; if( divide < 100 ) precision = distance < 10 ? 1 : 0; else precision = distance < 3 ? 3 : distance < 110 ? 2 : distance < 1100 ? 1 : 0; var pow = Math.pow(10, precision); return (Math.round(distance * pow) / pow) + ' ' + suffix; } }); var metric = ui && 'metric' in ui.options ? ui.options.metric : true; var map = control.map; var mc = map._measureControl = new MC(control, { metric: metric }); if( ui.strings.totalLength && ui.strings.singleLength ) { mc.options.prefixTotal = ui.strings.totalLength; mc.options.prefixSingle = ui.strings.singleLength; } if( ui.options.measureButton ) { mc.options.button = true; mc.options.position = 'topleft'; } map.addControl(mc); map.on('draw:created', function(e) { // by this moment e.layer is not added to the drawing mc.updateLength(null, e.layer); }); mc.updateLength(); } });