/* eslint-disable */
|
!(function() {
|
'use strict'
|
|
L.Marker.Measurement = L[L.Layer ? 'Layer' : 'Class'].extend({
|
options: {
|
pane: 'markerPane'
|
},
|
|
initialize: function(latlng, measurement, title, rotation, options) {
|
L.setOptions(this, options)
|
|
this._latlng = latlng
|
this._measurement = measurement
|
this._title = title
|
this._rotation = rotation
|
},
|
|
addTo: function(map) {
|
map.addLayer(this)
|
return this
|
},
|
|
onAdd: function(map) {
|
this._map = map
|
var pane = this.getPane ? this.getPane() : map.getPanes().markerPane
|
var el = this._element = L.DomUtil.create('div', 'leaflet-zoom-animated leaflet-measure-path-measurement', pane)
|
var inner = L.DomUtil.create('div', '', el)
|
inner.title = this._title
|
inner.innerHTML = this._measurement
|
|
map.on('zoomanim', this._animateZoom, this)
|
|
this._setPosition()
|
},
|
|
onRemove: function(map) {
|
map.off('zoomanim', this._animateZoom, this)
|
var pane = this.getPane ? this.getPane() : map.getPanes().markerPane
|
pane.removeChild(this._element)
|
this._map = null
|
},
|
|
_setPosition: function() {
|
L.DomUtil.setPosition(this._element, this._map.latLngToLayerPoint(this._latlng))
|
this._element.style.transform += ' rotate(' + this._rotation + 'rad)'
|
},
|
|
_animateZoom: function(opt) {
|
var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round()
|
L.DomUtil.setPosition(this._element, pos)
|
this._element.style.transform += ' rotate(' + this._rotation + 'rad)'
|
}
|
})
|
|
L.marker.measurement = function(latLng, measurement, title, rotation, options) {
|
return new L.Marker.Measurement(latLng, measurement, title, rotation, options)
|
}
|
|
var formatDistance = function(d) {
|
var unit,
|
feet
|
|
if (this._measurementOptions.imperial) {
|
feet = d / 0.3048
|
if (feet > 3000) {
|
d = d / 1609.344
|
unit = 'mi'
|
} else {
|
d = feet
|
unit = 'ft'
|
}
|
} else {
|
if (d > 1000) {
|
d = d / 1000
|
unit = 'km'
|
} else {
|
unit = 'm'
|
}
|
}
|
|
if (d < 100) {
|
return d.toFixed(1) + ' ' + unit
|
} else {
|
return Math.round(d) + ' ' + unit
|
}
|
}
|
|
var formatArea = function(a) {
|
var unit,
|
sqfeet
|
|
if (this._measurementOptions.imperial) {
|
if (a > 404.685642) {
|
a = a / 4046.85642
|
unit = 'ac'
|
} else {
|
a = a / 0.09290304
|
unit = 'ft²'
|
}
|
} else {
|
if (a > 1000000) {
|
a = a / 1000000
|
unit = 'km²'
|
} else {
|
unit = 'm²'
|
}
|
}
|
|
if (a < 100) {
|
return a.toFixed(1) + ' ' + unit
|
} else {
|
return Math.round(a) + ' ' + unit
|
}
|
}
|
|
var RADIUS = 6378137
|
// ringArea function copied from geojson-area
|
// (https://github.com/mapbox/geojson-area)
|
// This function is distributed under a separate license,
|
// see LICENSE.md.
|
var ringArea = function ringArea(coords) {
|
var rad = function rad(_) {
|
return _ * Math.PI / 180
|
}
|
var p1, p2, p3, lowerIndex, middleIndex, upperIndex,
|
area = 0,
|
coordsLength = coords.length
|
|
if (coordsLength > 2) {
|
for (var i = 0; i < coordsLength; i++) {
|
if (i === coordsLength - 2) {// i = N-2
|
lowerIndex = coordsLength - 2
|
middleIndex = coordsLength -1
|
upperIndex = 0
|
} else if (i === coordsLength - 1) {// i = N-1
|
lowerIndex = coordsLength - 1
|
middleIndex = 0
|
upperIndex = 1
|
} else { // i = 0 to N-3
|
lowerIndex = i
|
middleIndex = i+1
|
upperIndex = i+2
|
}
|
p1 = coords[lowerIndex]
|
p2 = coords[middleIndex]
|
p3 = coords[upperIndex]
|
area += ( rad(p3.lng) - rad(p1.lng) ) * Math.sin( rad(p2.lat))
|
}
|
|
area = area * RADIUS * RADIUS / 2
|
}
|
|
return Math.abs(area)
|
}
|
/**
|
* Handles the init hook for polylines and circles.
|
* Implements the showOnHover functionality if called for.
|
*/
|
var addInitHook = function() {
|
var showOnHover = this.options.measurementOptions && this.options.measurementOptions.showOnHover
|
if (this.options.showMeasurements && !showOnHover) {
|
this.showMeasurements()
|
}
|
if (this.options.showMeasurements && showOnHover) {
|
this.on('mouseover', function() {
|
this.showMeasurements()
|
})
|
this.on('mouseout', function() {
|
this.hideMeasurements()
|
})
|
}
|
}
|
|
var circleArea = function circleArea(d) {
|
var rho = d / RADIUS
|
return 2 * Math.PI * RADIUS * RADIUS * (1 - Math.cos(rho))
|
}
|
|
var override = function(method, fn, hookAfter) {
|
if (!hookAfter) {
|
return function() {
|
var originalReturnValue = method.apply(this, arguments)
|
var args = Array.prototype.slice.call(arguments)
|
args.push(originalReturnValue)
|
return fn.apply(this, args)
|
}
|
} else {
|
return function() {
|
fn.apply(this, arguments)
|
return method.apply(this, arguments)
|
}
|
}
|
}
|
|
L.Polyline.include({
|
showMeasurements: function(options) {
|
if (!this._map || this._measurementLayer) return this
|
|
this._measurementOptions = L.extend({
|
showOnHover: (options && options.showOnHover) || false,
|
minPixelDistance: 30,
|
showDistances: true,
|
showArea: true,
|
showTotalDistance: true,
|
lang: {
|
totalLength: 'Total length',
|
totalArea: 'Total area',
|
segmentLength: 'Segment length'
|
}
|
}, options || {})
|
|
this._measurementLayer = L.layerGroup().addTo(this._map)
|
this.updateMeasurements()
|
|
this._map.on('zoomend', this.updateMeasurements, this)
|
|
return this
|
},
|
|
hideMeasurements: function() {
|
if (!this._map) return this
|
|
this._map.off('zoomend', this.updateMeasurements, this)
|
|
if (!this._measurementLayer) return this
|
this._map.removeLayer(this._measurementLayer)
|
this._measurementLayer = null
|
|
return this
|
},
|
|
onAdd: override(L.Polyline.prototype.onAdd, function(originalReturnValue) {
|
var showOnHover = this.options.measurementOptions && this.options.measurementOptions.showOnHover
|
if (this.options.showMeasurements && !showOnHover) {
|
this.showMeasurements(this.options.measurementOptions)
|
}
|
|
return originalReturnValue
|
}),
|
|
onRemove: override(L.Polyline.prototype.onRemove, function(originalReturnValue) {
|
this.hideMeasurements()
|
|
return originalReturnValue
|
}, true),
|
|
setLatLngs: override(L.Polyline.prototype.setLatLngs, function(originalReturnValue) {
|
this.updateMeasurements()
|
|
return originalReturnValue
|
}),
|
|
spliceLatLngs: override(L.Polyline.prototype.spliceLatLngs, function(originalReturnValue) {
|
this.updateMeasurements()
|
|
return originalReturnValue
|
}),
|
|
formatDistance: formatDistance,
|
formatArea: formatArea,
|
|
updateMeasurements: function() {
|
if (!this._measurementLayer) return this
|
|
var latLngs = this.getLatLngs(),
|
isPolygon = this instanceof L.Polygon,
|
options = this._measurementOptions,
|
totalDist = 0,
|
formatter,
|
ll1,
|
ll2,
|
p1,
|
p2,
|
pixelDist,
|
dist
|
|
if (latLngs && latLngs.length && L.Util.isArray(latLngs[0])) {
|
// Outer ring is stored as an array in the first element,
|
// use that instead.
|
latLngs = latLngs[0]
|
}
|
|
this._measurementLayer.clearLayers()
|
|
if (this._measurementOptions.showDistances && latLngs.length > 1) {
|
formatter = this._measurementOptions.formatDistance || L.bind(this.formatDistance, this)
|
|
for (var i = 1, len = latLngs.length; (isPolygon && i <= len) || i < len; i++) {
|
ll1 = latLngs[i - 1]
|
ll2 = latLngs[i % len]
|
dist = ll1.distanceTo(ll2)
|
totalDist += dist
|
|
p1 = this._map.latLngToLayerPoint(ll1)
|
p2 = this._map.latLngToLayerPoint(ll2)
|
|
pixelDist = p1.distanceTo(p2)
|
|
if (pixelDist >= options.minPixelDistance) {
|
L.marker.measurement(
|
this._map.layerPointToLatLng([(p1.x + p2.x) / 2, (p1.y + p2.y) / 2]),
|
formatter(dist), options.lang.segmentLength, this._getRotation(ll1, ll2), options)
|
.addTo(this._measurementLayer)
|
}
|
}
|
|
// Show total length for polylines
|
if (!isPolygon && this._measurementOptions.showTotalDistance) {
|
L.marker.measurement(ll2, formatter(totalDist), options.lang.totalLength, 0, options)
|
.addTo(this._measurementLayer)
|
}
|
}
|
|
if (isPolygon && options.showArea && latLngs.length > 2) {
|
formatter = options.formatArea || L.bind(this.formatArea, this)
|
var area = ringArea(latLngs)
|
L.marker.measurement(this.getBounds().getCenter(),
|
formatter(area), options.lang.totalArea, 0, options)
|
.addTo(this._measurementLayer)
|
}
|
|
return this
|
},
|
|
_getRotation: function(ll1, ll2) {
|
var p1 = this._map.project(ll1),
|
p2 = this._map.project(ll2)
|
|
return Math.atan((p2.y - p1.y) / (p2.x - p1.x))
|
}
|
})
|
|
L.Polyline.addInitHook(function() {
|
addInitHook.call(this)
|
})
|
|
L.Circle.include({
|
showMeasurements: function(options) {
|
if (!this._map || this._measurementLayer) return this
|
|
this._measurementOptions = L.extend({
|
showOnHover: false,
|
showArea: true,
|
lang: {
|
totalArea: 'Total area',
|
}
|
}, options || {})
|
|
this._measurementLayer = L.layerGroup().addTo(this._map)
|
this.updateMeasurements()
|
|
this._map.on('zoomend', this.updateMeasurements, this)
|
|
return this
|
},
|
|
hideMeasurements: function() {
|
if (!this._map) return this
|
|
this._map.on('zoomend', this.updateMeasurements, this)
|
|
if (!this._measurementLayer) return this
|
this._map.removeLayer(this._measurementLayer)
|
this._measurementLayer = null
|
|
return this
|
},
|
|
onAdd: override(L.Circle.prototype.onAdd, function(originalReturnValue) {
|
var showOnHover = this.options.measurementOptions && this.options.measurementOptions.showOnHover
|
if (this.options.showMeasurements && !showOnHover) {
|
this.showMeasurements(this.options.measurementOptions)
|
}
|
|
return originalReturnValue
|
}),
|
|
onRemove: override(L.Circle.prototype.onRemove, function(originalReturnValue) {
|
this.hideMeasurements()
|
|
return originalReturnValue
|
}, true),
|
|
setLatLng: override(L.Circle.prototype.setLatLng, function(originalReturnValue) {
|
this.updateMeasurements()
|
|
return originalReturnValue
|
}),
|
|
setRadius: override(L.Circle.prototype.setRadius, function(originalReturnValue) {
|
this.updateMeasurements()
|
|
return originalReturnValue
|
}),
|
|
formatArea: formatArea,
|
|
updateMeasurements: function() {
|
if (!this._measurementLayer) return
|
|
var latLng = this.getLatLng(),
|
options = this._measurementOptions,
|
formatter = options.formatArea || L.bind(this.formatArea, this)
|
|
this._measurementLayer.clearLayers()
|
|
if (options.showArea) {
|
formatter = options.formatArea || L.bind(this.formatArea, this)
|
var area = circleArea(this.getRadius())
|
L.marker.measurement(latLng,
|
formatter(area), options.lang.totalArea, 0, options)
|
.addTo(this._measurementLayer)
|
}
|
}
|
})
|
|
L.Circle.addInitHook(function() {
|
addInitHook.call(this)
|
})
|
})()
|