I'm refactoring the whole code of the app with modules and I'm having some problem with the Ruler function of OpenLayers 4 now.
In the previous code was working OK, but now when I double click on the map to stop the current measure and start a new one, the only thing left in the screen is the popup, the line (the line of what I was measuring before) is removed.
Here my code:
const initVector = (mapView) => {
/**
* vector layers sources
*/
$('.form-inline').click(function () {
addRuler()
alert("initialize")
})
let Rsource = new ol.source.Vector()
let rulerLayer = new ol.layer.Vector({
source: Rsource,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(0, 0, 0, 0.7)',
width: 3
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: 'rgba(0, 0, 0, 0.7)'
})
})
})
})
/*
* ruler tool handler
*/
/**
* global vars
*/
// this style is done by javascript to bypass the override rule that enter in conflict with FRA
$('.markers button').css({'margin': '5px 7px', 'padding': '0 10px'})
$('#markloc').css('margin-left', '5px')
// these var are for the creation of the text and all the related element during the measure
let sketch
let helpTooltipElement
let helpTooltip
let measureTooltipElement
let measureTooltip
let ruler
/*
* pointer handler
*/
const pointerMoveHandler = (evt) => {
/*
* if the mouse is dragging the map return
*/
if (evt.dragging) {
return
}
/**
* default message to display
*/
let helpMsg = 'Click to start drawing'
/**
* check the message if you are measuring
*/
if (sketch) {
helpMsg = 'Click to continue drawing the line or double click to stop.'
}
/**
* attach to the tooltip the correct message
* set the position near the mouse cursor
* display the tooltip
*/
helpTooltipElement.innerHTML = helpMsg
helpTooltip.setPosition(evt.coordinate)
helpTooltipElement.classList.remove('hidden')
}
/**
* display the actual measured length
*/
function formatLength (line) {
const length = ol.Sphere.getLength(line)
let output
if (length > 100) {
output = `${Math.round(length / 1000 * 100) / 100} km`
}
else {
output = `${Math.round(length * 100) / 100} m`
}
return output
}
/**
* create a new tooltip
*/
function createHelpTooltip () {
helpTooltipElement = document.createElement('div')
helpTooltipElement.className = 'tooltip hidden'
helpTooltip = new ol.Overlay({
element: helpTooltipElement,
offset: [15, 0],
positioning: 'center-left'
})
mapView.addOverlay(helpTooltip)
}
/**
* Creates a new measure tooltip
*/
function createMeasureTooltip () {
measureTooltipElement = document.createElement('div')
measureTooltipElement.className = 'tooltip tooltip-measure'
measureTooltip = new ol.Overlay({
element: measureTooltipElement,
offset: [0, -15],
positioning: 'bottom-center'
})
mapView.addOverlay(measureTooltip)
}
/**
* add the ruler when you click on the button
*/
function addRuler () {
/**
* add a selected class to the ruler button to make it visible that it's in use
*/
$('#tlruler').addClass('custbtnsel')
/**
* styling ruler
*/
ruler = new ol.interaction.Draw({
source: Rsource,
type: 'LineString',
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(0, 0, 0, 0.5)',
lineDash: [10, 10],
width: 2
}),
image: new ol.style.Circle({
radius: 5,
stroke: new ol.style.Stroke({
color: 'rgba(0, 0, 0, 0.7)'
})
})
})
})
/**
* call the pointerMoveHandler to create the element on the screen when the ruler it's in use
*/
mapView.on('pointermove', pointerMoveHandler)
/**
* mouseout event listener to hidden the popup
*/
mapView.getViewport().addEventListener('mouseout', () => {
helpTooltipElement.classList.add('hidden')
})
/**
* add the ruler interaction to the map
*/
mapView.addInteraction(ruler)
/**
* create the tooltip
*/
createMeasureTooltip()
createHelpTooltip()
let listener
/**
* drawstart event
*/
ruler.on('drawstart', function (evt) {
// set sketch
sketch = evt.feature
// tooltip coordinate
let tooltipCoord = evt.coordinate
/**
* sketch event listener on change
* called during a mouse move
*/
listener = sketch.getGeometry().on('change', function (evt) {
let geom = evt.target
/**
* as we don't use polygon we check justfor line
* get last position of the cursor and the length
*/
let output
// OL 5 CODE
// if (geom instanceof LineString)
if (geom instanceof ol.geom.LineString) {
output = formatLength(geom)
tooltipCoord = geom.getLastCoordinate()
}
/**
* append to the tooltip the measure
* set the position of the tooltip to the last cursor coord
*/
measureTooltipElement.innerHTML = output
measureTooltip.setPosition(tooltipCoord)
})
}, this)
/**
* drawend event
*/
ruler.on('drawend', () => {
/**
* create the static tooltip with the last measure
*/
console.log('drawend')
measureTooltipElement.className = 'tooltip tooltip-static'
measureTooltip.setOffset([0, -7])
/**
* set sketch and the tooltip element to null
*/
sketch = null
measureTooltipElement = null
/**
* set sketch and the tooltip element to null
*/
createMeasureTooltip()
// OL 5 code
// unByKey(listener);
ol.Observable.unByKey(listener)
}, this)
/**
* end addRuler function
*/
}
}
const mapLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
let map = new ol.Map({
layers: [mapLayer],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 10
})
})
initVector(map)
the link to the pen so you can test it: (pen deleted)
and here how should work:
https://openlayers.org/en/latest/examples/measure.html
Notice that I created a function to initialise the ruler to simulate the module, as my map is created inside a module and the ruler in another, in the map module then I import that function and I initialise it with the map variable
Thanks to @Mike that answer me in Gis.stackexchange.
In initVector after creating rulerLayer you need to add it to the map map.addLayer(rulerLayer);
A very small error.