<!DOCTYPE html>
<html>

<head>
  <link data-require="leaflet@0.7.7" data-semver="0.7.7" rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.0/leaflet.css" />
  <script data-require="leaflet@0.7.7" data-semver="0.7.7" src="//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.0/leaflet.js"></script>
  <script src="https://npmcdn.com/leaflet-geometryutil"></script>
</head>

<body>
  <h1>Demo for 'closest' methods</h1>


  <p>
    To test, just click on the map to see the closest segment.<br>
    The <strong>closests point</strong> from polygon1, polyline1 and polyline2 will be displayed with a blue marker.<br>
    The <strong>closest layer</strong> will be switched in green and written after the method.<br>
    The <strong>closest layer by snap</strong> will just be written after the method.<br>
    The <strong>closest point on segment</strong> will be calculated with the red segment, and displayed as a marker on it.
  </p>

  <div id="map" style="height: 300px"></div>

  <pre>
    <code>closest(map, layer, latlng, vertices)</code>
    vertices parameter <input type="checkbox" id="p_vertices">
  </pre>
  
  <pre>
    <code style="color:green">closestLayer(map, layers, latlng) : <span id='closestLayer'></span> </code>
  </pre>
  
  <pre>
    <code>closestLayerSnap(map, layers, latlng, tolerance, withVertices) : <span id='closestLayerSnap'></span> </code>
    tolerance parameter (default Infinity if empty) <input type="number" id="p_tolerance">
    withVertices parameter <input type="checkbox" id="p_withVertices" checked>
  </pre>
  
  <pre>
    <code style="color:red">closestOnSegment(map, latlng, latlngA, latlngB)</code>
    <code id="closestOnSegment"></code>
  </pre>

  <script src="geojson.js"></script>
  <script src="script.js"></script>
  
</body>

</html>
var llPolyline1 = [ [39.76116, -105.03702], 
                  [39.76684, -105.01608], 
                  [39.76116, -104.95874]],
    llPolyline2 = [ [39.7572, -105.04217],
                   [39.74783, -105.04698],
                   [39.7308, -105.0432],
                  ],
    llSegment = [ [39.73397, -105.03256],
                  [39.73397, -104.93681]
                  ],
    llPolygon1 = [
      [[39.75324, -104.97934], 
                  [39.75879, -104.96681], 
                  [39.75379, -104.94681], 
                  [39.74379, -104.93681], 
                  [39.74348, -104.97711] ], // outer ring
      [ [39.75245, -104.97471], 
                  [39.7547, -104.9663], 
                  [39.75206, -104.95171], 
                  [39.74849, -104.94965], 
                  [39.74744, -104.97385] ] // hole
    ],
    
    _map = L.map('map').setView(/*[51.505, -0.09]*/ [39.74739, -105], 13),
    polygon1 = L.polygon(llPolygon1, {color: 'blue', className: 'polygon1'}).addTo(_map),
    polyline1 = L.polyline(llPolyline1, {color: 'blue', className: 'polyline1'}).addTo(_map),
    polyline2 = L.polyline(llPolyline2, {color: 'blue', className: 'polyline2'}).addTo(_map),
    segment = L.polyline(llSegment, {color: 'red', className: 'segment'}).addTo(_map),
    marker = null,
    markerClosestPolygon1 = null,
    markerClosestPolyline1 = null,
    markerClosestPolyline2 = null,
    markerClosestSegment = null;


var bicycle = L.geoJson([bicycleRental, campus], {

  	style: function (feature) {
  		return feature.properties && feature.properties.style;
  	},
  
  	pointToLayer: function (feature, latlng) {
  		return L.circleMarker(latlng, {
  			radius: 8,
  			fillColor: "#ff7800",
  			color: "#000",
  			weight: 1,
  			opacity: 1,
  			fillOpacity: 0.8
  		});
  	}
  }).addTo(_map),

  freebusLayer = L.geoJson(freeBus, {

  	filter: function (feature, layer) {
  		if (feature.properties) {
  			// If the property "underConstruction" exists and is true, return false (don't render features under construction)
  			return feature.properties.underConstruction !== undefined ? !feature.properties.underConstruction : true;
  		}
  		return false;
  	}
  
  }).addTo(_map),
  
  coorsLayer = L.geoJson(coorsField, {
  
  	pointToLayer: function (feature, latlng) {
  		return L.marker(latlng, {className: 'marker'});
  	}
  	
  }).addTo(_map);

// console.log("latlngs of polygon1")
// console.log(polygon1.getLatLngs())
// console.log("latlngs of polyline1")
// console.log(polyline1.getLatLngs())
// console.log("latlngs of polyline2")
// console.log(polyline2.getLatLngs())

function init() {
  if (marker) _map.removeLayer(marker);
  if (markerClosestPolygon1) _map.removeLayer(markerClosestPolygon1);
  if (markerClosestPolyline1) _map.removeLayer(markerClosestPolyline1);
  if (markerClosestPolyline2) _map.removeLayer(markerClosestPolyline2);
  if (markerClosestSegment) _map.removeLayer(markerClosestSegment);
  
  polygon1.setStyle({color:'blue'});
  polyline1.setStyle({color:'blue'});
  polyline2.setStyle({color:'blue'});
  
   document.getElementById('closestLayer').innerHTML = '';
   document.getElementById('closestLayerSnap').innerHTML = '';
}

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(_map);

_map.on('click', function(e) {
  
  init();
  
  marker = L.marker(e.latlng).addTo(_map).bindPopup(e.latlng + '<br/>' + e.layerPoint).openPopup();
  
  var p_vertices = document.getElementById('p_vertices').checked,
      p_tolerance = document.getElementById('p_tolerance').value !== '' ? parseInt(document.getElementById('p_tolerance').value) : Infinity,
      p_withVertices = document.getElementById('p_withVertices').checked,
      closestPointToPolygon1 = L.GeometryUtil.closest(_map, polygon1, e.latlng, p_vertices),
      closestPointToPolyline1 = L.GeometryUtil.closest(_map, polyline1, e.latlng, p_vertices),
      closestPointToPolyline2 = L.GeometryUtil.closest(_map, polyline2, e.latlng, p_vertices),
      closestLayer = L.GeometryUtil.closestLayer(_map, bicycle.getLayers().concat(coorsLayer.getLayers(), polyline1, polyline2, polygon1), e.latlng),
      closestLayerSnap = L.GeometryUtil.closestLayerSnap(_map, [ polyline1, polygon1, polyline2 ], e.latlng, p_tolerance, p_withVertices),
      closestOnSegment = L.GeometryUtil.closestOnSegment(_map, e.latlng, llSegment[0], llSegment[1]);
  
  // display the closest points
  markerClosestPolygon1 = L.marker(closestPointToPolygon1).addTo(_map).bindPopup('Closest point on polygon1');
  markerClosestPolyline1 = L.marker(closestPointToPolyline1).addTo(_map).bindPopup('Closest point on polyline1');
  markerClosestPolyline2 = L.marker(closestPointToPolyline2).addTo(_map).bindPopup('Closest point on polyline2');
  
  // change the color of closest layer
  if (typeof closestLayer.layer.setStyle === 'function') {
    closestLayer.layer.setStyle({'color':'green'});
  }
  document.getElementById('closestLayer').innerHTML = closestLayer.layer.options.className;
  
  // display the closest position for snap
  document.getElementById('closestLayerSnap').innerHTML = closestLayerSnap ? closestLayerSnap.layer.options.className : 'unknown'; 
  
  // display the closest point on red segment
  markerClosestSegment = L.marker(closestOnSegment).addTo(_map).bindPopup('Closest point on segment');
  
})
Demo to test closest, closestLayer, closestLayerSnap and closestOnSegment methods of Leaflet.GeometryUtil plugin.
// data from leaflet documentation
// http://leafletjs.com/examples/geojson-example.html
var freeBus = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [-105.00341892242432, 39.75383843460583],
                    [-105.0008225440979, 39.751891803969535]
                ]
            },
            "properties": {
                "popupContent": "This is free bus that will take you across downtown.",
                "underConstruction": false
            },
            "id": 1
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [-105.0008225440979, 39.751891803969535],
                    [-104.99820470809937, 39.74979664004068]
                ]
            },
            "properties": {
                "popupContent": "This is free bus that will take you across downtown.",
                "underConstruction": true
            },
            "id": 2
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [-104.99820470809937, 39.74979664004068],
                    [-104.98689651489258, 39.741052354709055]
                ]
            },
            "properties": {
                "popupContent": "This is free bus that will take you across downtown.",
                "underConstruction": false
            },
            "id": 3
        }
    ]
};

var lightRailStop = {
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "popupContent": "18th & California Light Rail Stop"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [-104.98999178409576, 39.74683938093904]
            }
        },{
            "type": "Feature",
            "properties": {
                "popupContent": "20th & Welton Light Rail Stop"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [-104.98689115047453, 39.747924136466565]
            }
        }
    ]
};

var bicycleRental = {
    "type": "FeatureCollection",
    "features": [
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9998241,
                    39.7471494
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 51
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9983545,
                    39.7502833
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 52
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9963919,
                    39.7444271
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 54
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9960754,
                    39.7498956
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 55
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9933717,
                    39.7477264
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 57
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9913392,
                    39.7432392
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 58
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -104.9788452,
                    39.6933755
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is a B-Cycle Station. Come pick up a bike and pay by the hour. What a deal!"
            },
            "id": 74
        }
    ]
};

var campus = {
    "type": "Feature",
    "properties": {
        "popupContent": "This is the Auraria West Campus",
        "style": {
            weight: 2,
            color: "#999",
            opacity: 1,
            fillColor: "#B0DE5C",
            fillOpacity: 0.8
        }
    },
    "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
            [
                [
                    [-105.00432014465332, 39.74732195489861],
                    [-105.00715255737305, 39.74620006835170],
                    [-105.00921249389647, 39.74468219277038],
                    [-105.01067161560059, 39.74362625960105],
                    [-105.01195907592773, 39.74290029616054],
                    [-105.00989913940431, 39.74078835902781],
                    [-105.00758171081543, 39.74059036160317],
                    [-105.00346183776855, 39.74059036160317],
                    [-105.00097274780272, 39.74059036160317],
                    [-105.00062942504881, 39.74072235994946],
                    [-105.00020027160645, 39.74191033368865],
                    [-105.00071525573731, 39.74276830198601],
                    [-105.00097274780272, 39.74369225589818],
                    [-105.00097274780272, 39.74461619742136],
                    [-105.00123023986816, 39.74534214278395],
                    [-105.00183105468751, 39.74613407445653],
                    [-105.00432014465332, 39.74732195489861]
                ],[
                    [-105.00361204147337, 39.74354376414072],
                    [-105.00301122665405, 39.74278480127163],
                    [-105.00221729278564, 39.74316428375108],
                    [-105.00283956527711, 39.74390674342741],
                    [-105.00361204147337, 39.74354376414072]
                ]
            ],[
                [
                    [-105.00942707061768, 39.73989736613708],
                    [-105.00942707061768, 39.73910536278566],
                    [-105.00685214996338, 39.73923736397631],
                    [-105.00384807586671, 39.73910536278566],
                    [-105.00174522399902, 39.73903936209552],
                    [-105.00041484832764, 39.73910536278566],
                    [-105.00041484832764, 39.73979836621592],
                    [-105.00535011291504, 39.73986436617916],
                    [-105.00942707061768, 39.73989736613708]
                ]
            ]
        ]
    }
};

var coorsField = {
    "type": "Feature",
    "properties": {
        "popupContent": "Coors Field"
    },
    "geometry": {
        "type": "Point",
        "coordinates": [-104.99404191970824, 39.756213909328125]
    }
};