@@ -63,6 +63,24 @@ let CoordsPickerButton = ButtonBase.extend({
6363 } ,
6464} ) ;
6565
66+ let RulerButton = ButtonBase . extend ( {
67+ onAdd : function ( ) {
68+ let button = L . DomUtil . create ( "button" , "ion-ruler" ) ;
69+ button . setAttribute ( "aria-label" , _ . t ( "button.ruler" ) ) ;
70+ L . DomEvent . disableClickPropagation ( button ) ;
71+ L . DomEvent . addListener ( button , "click" , this . onClick , this ) ;
72+
73+ this . button = button ;
74+
75+ return button ;
76+ } ,
77+
78+ onClick : function ( e ) {
79+ L . DomEvent . stopPropagation ( e ) ;
80+ this . f ( ! this . active ) ;
81+ } ,
82+ } ) ;
83+
6684export const Button = function ( map , buttons ) {
6785 let userLocation ;
6886 const self = {
@@ -103,6 +121,99 @@ export const Button = function (map, buttons) {
103121 }
104122 } ) ;
105123
124+ // Ruler / measure distances button
125+ let rulerButton = new RulerButton ( function ( activate ) {
126+ if ( activate ) {
127+ enableRuler ( ) ;
128+ } else {
129+ disableRuler ( ) ;
130+ }
131+ } ) ;
132+
133+ let rulerLayerGroup = null ;
134+ let rulerMarkers = [ ] ;
135+ let rulerLines = null ;
136+ let rulerLinesBg = null ;
137+ let rulerDistancePopups = [ ] ;
138+
139+ function formatDistance ( m ) {
140+ if ( m >= 1000 ) {
141+ return ( m / 1000 ) . toFixed ( 2 ) + " km" ;
142+ }
143+ return Math . round ( m ) + " m" ;
144+ }
145+
146+ function enableRuler ( ) {
147+ // create layer group for ruler markers/lines
148+ rulerLayerGroup = L . layerGroup ( ) . addTo ( map ) ;
149+ rulerLinesBg = L . polyline ( [ ] , {
150+ color : "#fff" ,
151+ weight : 3 ,
152+ } ) . addTo ( rulerLayerGroup ) ;
153+ rulerLines = L . polyline ( [ ] , { color : "#000" , weight : 2 , dashArray : "4" } ) . addTo ( rulerLayerGroup ) ;
154+ rulerMarkers = [ ] ;
155+ rulerDistancePopups = [ ] ;
156+
157+ map . getContainer ( ) . classList . add ( "measure-active" ) ;
158+ map . on ( "click" , onRulerClick ) ;
159+ rulerButton . set ( true ) ;
160+ }
161+
162+ function disableRuler ( ) {
163+ map . getContainer ( ) . classList . remove ( "measure-active" ) ;
164+ map . off ( "click" , onRulerClick ) ;
165+
166+ if ( rulerLayerGroup ) {
167+ map . removeLayer ( rulerLayerGroup ) ;
168+ rulerLayerGroup = null ;
169+ }
170+ rulerMarkers = [ ] ;
171+ rulerLines = null ;
172+ rulerLinesBg = null ;
173+ rulerDistancePopups = [ ] ;
174+
175+ rulerButton . set ( false ) ;
176+ }
177+
178+ function onRulerClick ( e ) {
179+ let latlng = e . latlng ;
180+ let config = window . config ;
181+ let marker = L . circleMarker ( latlng , {
182+ radius : 5 ,
183+ color : config . map && config . map . labelNewColor ? config . map . labelNewColor : "#333" ,
184+ } ) . addTo ( rulerLayerGroup ) ;
185+ rulerMarkers . push ( marker ) ;
186+
187+ // add to polyline
188+ let latlngs = rulerLines . getLatLngs ( ) ;
189+ latlngs . push ( latlng ) ;
190+ rulerLines . setLatLngs ( latlngs ) ;
191+ rulerLinesBg . setLatLngs ( latlngs ) ;
192+
193+ // compute segment distance and total distance
194+ let last = null ;
195+ if ( latlngs . length >= 2 ) {
196+ last = latlngs [ latlngs . length - 2 ] ;
197+ let segDist = latlng . distanceTo ( latlngs [ latlngs . length - 2 ] ) ;
198+ // show popup at midpoint for segment
199+ let midLat = ( latlng . lat + last . lat ) / 2 ;
200+ let midLng = ( latlng . lng + last . lng ) / 2 ;
201+
202+ // compute total
203+ let total = 0 ;
204+ for ( let i = 1 ; i < latlngs . length ; i ++ ) {
205+ total += latlngs [ i ] . distanceTo ( latlngs [ i - 1 ] ) ;
206+ }
207+
208+ let popup = L . popup ( { closeButton : false , autoClose : false , className : "ruler-popup" } )
209+ . setLatLng ( [ midLat , midLng ] )
210+ . setContent ( "<strong>" + formatDistance ( segDist ) + "</strong><br/>" + formatDistance ( total ) )
211+ . addTo ( rulerLayerGroup ) ;
212+
213+ rulerDistancePopups . push ( popup ) ;
214+ }
215+ }
216+
106217 function enableTracking ( ) {
107218 map . locate ( {
108219 watch : true ,
@@ -154,6 +265,7 @@ export const Button = function (map, buttons) {
154265 self . init = function init ( ) {
155266 addButton ( locateUserButton ) ;
156267 addButton ( showCoordsPickerButton ) ;
268+ addButton ( rulerButton ) ;
157269 } ;
158270
159271 return self ;
0 commit comments