I've took a stab at this using these steps:
- Use the drawing tools to enable a drawing experience.
- Use the drawing started, erased, and changing events to monitor the drawing state.
- When drawing started, create a layer for the distance labels of that shape. Add a reference to that layer in the metadata of that shape so we can remove that layer when the shape is erased. Measure the shape.
- When a shape is erased, grab the label layer reference from the shapes metadata and delete the layer.
- When the shape is changing, measure the length of each line segment and create a pushpin (or infobox) for each line. Choose where you want to display it. I choose 3/4 of the way down the line so that the both the end points and the middle point of the lines are not covered and can be grabbed with the mouse when editing. Replace the pushpins layer.
Here is a code sample (I didn't bother customizing the pushpin icon):
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<script>
var map, drawingManager, currentLayer;
function GetMap() {
map = new Microsoft.Maps.Map('#myMap', {});
//Load the Drawing Tools and Spatial Math modules.
Microsoft.Maps.loadModule(['Microsoft.Maps.DrawingTools', 'Microsoft.Maps.SpatialMath'], function () {
var tools = new Microsoft.Maps.DrawingTools(map);
tools.showDrawingManager(function (manager) {
//Store a reference to the drawing manager as it will be useful later.
drawingManager = manager;
var da = Microsoft.Maps.DrawingTools.DrawingBarAction;
manager.setOptions({
drawingBarActions: da.polyline | da.edit | da.erase
});
Microsoft.Maps.Events.addHandler(drawingManager, 'drawingChanging', measureShape);
Microsoft.Maps.Events.addHandler(drawingManager, 'drawingStarted', drawStarted);
Microsoft.Maps.Events.addHandler(drawingManager, 'drawingErased', drawingErased);
})
});
}
function drawStarted(shape) {
//Make sure the shape isn't attached to a layer for labels already.
if(!shape.metadata || !shape.metadata.layer) {
//Create a layer for current shape being drawn.
currentLayer = new Microsoft.Maps.Layer();
map.layers.insert(currentLayer);
//Add a reference to the shape in the metadata of the shape so we can remove the labels when the line is erased.
shape.metadata = {
layer: currentLayer
};
//Measure the shape.
measureShape(shape);
}
}
function drawingErased(shape) {
if(shape.metadata && shape.metadata.layer) {
map.layers.remove(shape.metadata.layer);
}
}
function measureShape(shape) {
if (shape instanceof Microsoft.Maps.Polyline) {
var points = shape.getLocations();
var distancePins = [];
//Measure the length of each line segment in a polyline, and calculate midpoints for the labels pins.
for(var i = 0; i < points.length - 1; i++) {
var length = Microsoft.Maps.SpatialMath.getDistanceTo(points[i], points[i + 1], Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers);
//Round values to 2 decimals.
length = Math.round(length * 100) / 100;
//Add the pin close to the end of the line, but not at the very end, otherwise we won't be able to grab the point for editting the line.
//Keep the middle clear so that the midpoint can be grabbed for inserting points when drawing.
var pinLocation = Microsoft.Maps.SpatialMath.interpolate(points[i], points[i + 1], 0.75);
distancePins.push(new Microsoft.Maps.Pushpin(pinLocation, {
text: length + 'km'
}));
}
//Replace pins in layer.
currentLayer.clear();
currentLayer.add(distancePins);
}
}
</script>
</head>
<body>
<div id="myMap" style="position:relative;width:100%;height:800px;"></div>
<script src="https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=<YOUR_BING_MAPS_KEY>"></script>
</body>
</html>