From cb23f068da7ed41920bb9b9929f6159fa88dd75a Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Sat, 24 Feb 2018 20:23:20 +0100 Subject: [PATCH] Greatly improve marker/line highlight handling --- frontend/app/leaflet/highlightableLayers.js | 310 ++++++++++++++++++ frontend/app/leaflet/highlightableLayers.scss | 19 ++ frontend/app/map/lines/lines.js | 53 +-- frontend/app/map/map/map.js | 25 -- frontend/app/map/map/map.scss | 16 - frontend/app/map/markers/markers.js | 31 +- frontend/app/map/route/route.js | 42 +-- frontend/app/search/search-query.js | 54 +-- frontend/app/utils/utils.js | 5 +- 9 files changed, 375 insertions(+), 180 deletions(-) create mode 100644 frontend/app/leaflet/highlightableLayers.js create mode 100644 frontend/app/leaflet/highlightableLayers.scss diff --git a/frontend/app/leaflet/highlightableLayers.js b/frontend/app/leaflet/highlightableLayers.js new file mode 100644 index 00000000..e1d18140 --- /dev/null +++ b/frontend/app/leaflet/highlightableLayers.js @@ -0,0 +1,310 @@ +import fm from '../app'; +import $ from 'jquery'; +import L from 'leaflet'; +import ng from 'angular'; +import 'leaflet-almostover'; + +fm.app.factory("fmHighlightableLayers", function(fmUtils) { + + class Marker extends L.Marker { + + constructor(latLng, options) { + options = Object.assign({ + riseOnHover: true + }, options); + super(latLng, options); + + this.on("mouseover", () => { + this._mouseover = true; + this._initIcon(); + }); + this.on("mouseout", () => { + this._mouseover = false; + this._initIcon(); + }); + } + + onAdd() { + fmHighlightableLayers._prepareMap(this._map); + super.onAdd(...arguments); + } + + _initIcon() { + this.options.icon = fmUtils.createMarkerIcon(this.options.colour, this.options.size, this.options.symbol, this.options.shape, this.options.padding, this.options.highlight); + + super._initIcon(...arguments); + + this.setOpacity(this.options.highlight || this._mouseover ? 1 : 0.6); + + fmHighlightableLayers._updatePane(this, this.options.highlight ? "fmHighlightMarkerPane" : "markerPane"); + } + + setStyle(style) { + L.Util.setOptions(this, style); + this._initIcon(); + return this; + } + + } + + + class Polyline extends L.Polyline { + + constructor(latLngs, options) { + super(latLngs, options); + + this.borderLayer = new L.Polyline(latLngs, Object.assign({}, options, { interactive: false })); + } + + onAdd() { + fmHighlightableLayers._prepareMap(this._map); + super.onAdd(...arguments); + + this._map.addLayer(this.borderLayer); + this._map.almostOver.addLayer(this); + + this._updateStyle(); + } + + onRemove() { + this._map.almostOver.removeLayer(this); + this._map.removeLayer(this.borderLayer); + + super.onRemove(...arguments); + } + + _updateStyle() { + this.options.opacity = this.borderLayer.options.opacity = this.options.highlight ? 1 : 0.35; + this.borderLayer.options.weight = this.options.weight * 2; + this.borderLayer.options.color = "#"+fmUtils.makeTextColour(this.options.color.replace(/^#/, "")); + + fmHighlightableLayers._updatePane(this, this.options.highlight ? "fmHighlightPane" : "overlayPane"); + fmHighlightableLayers._updatePane(this.borderLayer, this.options.highlight ? "fmHighlightShadowPane" : "fmShadowPane"); + } + + redraw() { + this._updateStyle(); + super.redraw(...arguments); + this.borderLayer.redraw(); + return this; + } + + setStyle(style) { + L.Util.setOptions(this, style); + L.Util.setOptions(this.borderLayer, style); + this._updateStyle(); + super.setStyle({}); + this.borderLayer.setStyle({}); + return this; + } + + setLatLngs(latLngs) { + super.setLatLngs(...arguments); + this.borderLayer.setLatLngs(...arguments); + return this; + } + + fire(type, data, propagate) { + // Ignore DOM mouse events, otherwise we get them double, once by DOM, once by almostOver + if([ "mouseover", "mousemove", "mouseout" ].includes(type) && (!data.type || !data.type.startsWith("almost:"))) + return; + + return super.fire.apply(this, arguments); + } + + } + + + class Polygon extends L.Polygon { + + constructor(latLngs, options) { + super(latLngs, options); + + this.borderLayer = new L.Polygon(latLngs, Object.assign({}, options, { interactive: false })); + } + + onAdd() { + fmHighlightableLayers._prepareMap(this._map); + super.onAdd(...arguments); + this._map.addLayer(this.borderLayer); + + this._updateStyle(); + } + + onRemove() { + this._map.removeLayer(this.borderLayer); + super.onRemove(...arguments); + } + + _updateStyle() { + this.borderLayer.options.fill = this.options.highlight; + this.borderLayer.options.fillColor = "#"+fmUtils.makeTextColour(this.options.color.replace(/^#/, "")); + return Polyline.prototype._updateStyle.apply(this, arguments); + } + + redraw() { + this._updateStyle(); + super.redraw(...arguments); + this.borderLayer.redraw(); + return this; + } + + setStyle(style) { + L.Util.setOptions(this, style); + L.Util.setOptions(this.borderLayer, style); + this._updateStyle(); + super.setStyle({}); + this.borderLayer.setStyle({}); + return this; + } + + setLatLngs(latLngs) { + super.setLatLngs(...arguments); + this.borderLayer.setLatLngs(...arguments); + return this; + } + + } + + + class GeoJSON extends L.GeoJSON { + + addData(geojson) { + var features = Array.isArray(geojson) ? geojson : geojson.features, + i, len, feature; + + if (features) { + for (i = 0, len = features.length; i < len; i++) { + // only add this if geometry or geometries are set and not null + feature = features[i]; + if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { + this.addData(feature); + } + } + return this; + } + + var options = this.options; + + if (options.filter && !options.filter(geojson)) { return this; } + + var layer = this.geometryToLayer(geojson, options); + if (!layer) { + return this; + } + layer.feature = L.GeoJSON.asFeature(geojson); + + layer.defaultOptions = layer.options; + this.resetStyle(layer); + + if (options.onEachFeature) { + options.onEachFeature(geojson, layer); + } + + return this.addLayer(layer); + } + + geometryToLayer(geojson, options) { + var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, + coords = geometry ? geometry.coordinates : null, + layers = [], + _coordsToLatLng = options && options.coordsToLatLng || L.GeoJSON.coordsToLatLng.coordsToLatLng, + latlng, latlngs, i, len; + + if (!coords && !geometry) { + return null; + } + + switch (geometry.type) { + case 'Point': + latlng = _coordsToLatLng(coords); + return new fmHighlightableLayers.Marker(latlng, this.options.markerOptions); + + case 'MultiPoint': + for (i = 0, len = coords.length; i < len; i++) { + latlng = _coordsToLatLng(coords[i]); + layers.push(new fmHighlightableLayers.Marker(latlng, this.options.markerOptions)); + } + return new FeatureGroup(layers); + + case 'LineString': + case 'MultiLineString': + latlngs = L.GeoJSON.coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng); + return new fmHighlightableLayers.Polyline(latlngs, this.options); + + case 'Polygon': + case 'MultiPolygon': + latlngs = L.GeoJSON.coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng); + return new fmHighlightableLayers.Polygon(latlngs, this.options); + + case 'GeometryCollection': + for (i = 0, len = geometry.geometries.length; i < len; i++) { + var layer = this.geometryToLayer({ + geometry: geometry.geometries[i], + type: 'Feature', + properties: geojson.properties + }, options); + + if (layer) { + layers.push(layer); + } + } + return new L.FeatureGroup(layers); + + default: + throw new Error('Invalid GeoJSON object.'); + } + } + + } + + + let fmHighlightableLayers = { + _prepareMap(map) { + if(map._fmHighlightableLayersPrepared) + return; + + for(let paneName of [ "fmHighlightMarkerPane", "fmHighlightShadowPane", "fmHighlightPane", "fmShadowPane" ]) + map.createPane(paneName); + + map.almostOver.options.distance = 10; + + map.on('almost:over', (e) => { + e.layer.fire('mouseover', e, true); + $(map.getContainer()).addClass("fm-almostover"); + }); + + map.on('almost:out', (e) => { + e.layer.fire('mouseout', e, true); + $(map.getContainer()).removeClass("fm-almostover"); + }); + + map.on('almost:click', (e) => { + e.layer.fire('click', e, true); + }); + + map.on('almost:move', (e) => { + e.layer.fire('mousemove', e, true); + }); + + map._fmHighlightableLayersPrepared = true; + }, + + _updatePane(layer, pane) { + if(layer.options.pane == pane) + return; + + layer.options.pane = pane; + if(layer._map) + layer._map.removeLayer(layer).addLayer(layer); + }, + + Marker, + Polygon, + Polyline, + GeoJSON + }; + + return fmHighlightableLayers; + +}); diff --git a/frontend/app/leaflet/highlightableLayers.scss b/frontend/app/leaflet/highlightableLayers.scss new file mode 100644 index 00000000..d2e26b88 --- /dev/null +++ b/frontend/app/leaflet/highlightableLayers.scss @@ -0,0 +1,19 @@ +.leaflet-fmHighlightMarker-pane { + z-index: 621; +} + +.leaflet-fmHighlight-pane { + z-index: 620; +} + +.leaflet-fmHighlightShadow-pane { + z-index: 619; +} + +.leaflet-fmShadow-pane { + z-index: 399; +} + +.fm-almostover { + cursor: pointer !important; +} diff --git a/frontend/app/map/lines/lines.js b/frontend/app/map/lines/lines.js index 74359cc2..f787c0af 100644 --- a/frontend/app/map/lines/lines.js +++ b/frontend/app/map/lines/lines.js @@ -7,12 +7,11 @@ import {saveAs} from 'file-saver'; import css from './lines.scss'; -fm.app.factory("fmMapLines", function(fmUtils, $uibModal, $compile, $timeout, $rootScope) { +fm.app.factory("fmMapLines", function(fmUtils, $uibModal, $compile, $timeout, $rootScope, fmHighlightableLayers) { return function(map) { var linesById = { }; let openLine = null; - let openLineHighlight = null; let linePopupBaseScope = $rootScope.$new(); linePopupBaseScope.persistentSettings = {}; @@ -65,33 +64,23 @@ fm.app.factory("fmMapLines", function(fmUtils, $uibModal, $compile, $timeout, $r return linesUi._deleteLine(line); if(!linesById[line.id]) { - linesById[line.id] = L.polyline([ ]).addTo(map.map); - map.map.almostOver.addLayer(linesById[line.id]); + linesById[line.id] = (new fmHighlightableLayers.Polyline([ ])).addTo(map.map); if(line.id != null) { // We don't want a popup for lines that we are drawing right now linesById[line.id] .on("click", function(e) { linesUi.showLineInfoBox(map.client.lines[line.id]); }.fmWrapApply($rootScope)) - .on("fm-almostover", function(e) { - if(!linesById[line.id].getTooltip()) - linesById[line.id].bindTooltip("", $.extend({}, map.tooltipOptions, { permanent: true, offset: [ 20, 0 ] })); - + .bindTooltip("", $.extend({}, map.tooltipOptions, { sticky: true, offset: [ 20, 0 ] })) + .on("tooltipopen", function(e) { linesById[line.id].setTooltipContent(fmUtils.quoteHtml(map.client.lines[line.id].name)).openTooltip(e.latlng); - }) - .on("fm-almostmove", function(e) { - linesById[line.id].openTooltip(e.latlng); - }) - .on("fm-almostout", function() { - linesById[line.id].unbindTooltip(); }); } } var style = { color : '#'+line.colour, - weight : line.width, - opacity : 0.5 + weight : line.width }; // Two points that are both outside of the viewport should not be connected, as the piece in between @@ -100,24 +89,11 @@ fm.app.factory("fmMapLines", function(fmUtils, $uibModal, $compile, $timeout, $r linesById[line.id].setLatLngs(splitLatLngs).setStyle(style); - if(line.id != null && openLine && line.id == openLine.id) { - openLineHighlight.setLatLngs(splitLatLngs).setStyle(Object.assign(style, { - weight: Math.round(line.width*2), - color: "#"+fmUtils.makeTextColour(line.colour), - opacity: 1 - })); - - if(!_doNotRerenderPopup) - linesUi.showLineInfoBox(line); - } + if(line.id != null && openLine && line.id == openLine.id && !_doNotRerenderPopup) + linesUi.showLineInfoBox(line); }, _deleteLine: function(line) { if(line.id != null && openLine && line.id == openLine.id) { - if(openLineHighlight) { - openLineHighlight.remove(); - openLineHighlight = null; - } - openLine.hide(); openLine = null; } @@ -162,26 +138,15 @@ fm.app.factory("fmMapLines", function(fmUtils, $uibModal, $compile, $timeout, $r hide: map.infoBox.show(template, scope, () => { openLine = null; if(linesById[line.id]) { // Does not exist anymore after line was deleted - linesById[line.id].remove(); - linesById[line.id].options.pane = "overlayPane"; - linesById[line.id].addTo(map.map); + linesById[line.id].setStyle({ highlight: false }); } - if(openLineHighlight) - openLineHighlight.remove(); scope.$destroy(); }).hide, id: line.id }; - openLineHighlight = L.polyline([ ], { - pane: "fmHighlightShadowPane", - interactive: false - }).addTo(map.map); - - linesById[line.id].remove(); - linesById[line.id].options.pane = "fmHighlightPane"; - linesById[line.id].addTo(map.map); + linesById[line.id].setStyle({ highlight: true }); linesUi._addLine(line, true); // To render the openLineHighlight diff --git a/frontend/app/map/map/map.js b/frontend/app/map/map/map.js index 0a0e208d..b45f7add 100644 --- a/frontend/app/map/map/map.js +++ b/frontend/app/map/map/map.js @@ -1,7 +1,6 @@ import fm from '../../app'; import $ from 'jquery'; import L from 'leaflet'; -import 'leaflet-almostover'; import 'leaflet.locatecontrol'; import 'leaflet.markercluster'; import 'leaflet-mouse-position'; @@ -146,10 +145,6 @@ fm.app.directive("facilmap", function(fmUtils, fmMapMessages, fmMapMarkers, $com this.map = L.map($(".fm-map", $element)[0]); - this.map.createPane("fmHighlightMarkerPane"); - this.map.createPane("fmHighlightShadowPane"); - this.map.createPane("fmHighlightPane"); - this.map._controlCorners.bottomcenter = L.DomUtil.create("div", "leaflet-bottom fm-leaflet-center", this.map._controlContainer); $scope.$watch("client.padData.clusterMarkers", (clusterMarkers) => { @@ -172,8 +167,6 @@ fm.app.directive("facilmap", function(fmUtils, fmMapMessages, fmMapMarkers, $com this.markerCluster.addLayer(marker); }); - this.map.almostOver.options.distance = 10; - let locateControl = L.control.locate({ flyTo: true, icon: "a", @@ -193,24 +186,6 @@ fm.app.directive("facilmap", function(fmUtils, fmMapMessages, fmMapMarkers, $com position: "bottomcenter" }).addTo(this.map); - this.map.on('almost:over', (e) => { - e.layer.fire('fm-almostover', e); - $(this.map.getContainer()).addClass("fm-almostover"); - }); - - this.map.on('almost:out', (e) => { - e.layer.fire('fm-almostout', e); - $(this.map.getContainer()).removeClass("fm-almostover"); - }); - - this.map.on('almost:click', (e) => { - e.layer.fire('click', e, true); - }); - - this.map.on('almost:move', (e) => { - e.layer.fire('fm-almostmove', e); - }); - this.startMarkerColour = "00ff00"; this.dragMarkerColour = "ffd700"; this.endMarkerColour = "ff0000"; diff --git a/frontend/app/map/map/map.scss b/frontend/app/map/map/map.scss index 10cd7ee2..bf5f9283 100644 --- a/frontend/app/map/map/map.scss +++ b/frontend/app/map/map/map.scss @@ -11,10 +11,6 @@ height: 100%; } -.fm-almostover { - cursor: pointer !important; -} - .fm-clickHandler { cursor: crosshair; position: absolute; @@ -117,15 +113,3 @@ text-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 10px #fff; } } - -.leaflet-fmHighlightMarker-pane { - z-index: 621; -} - -.leaflet-fmHighlight-pane { - z-index: 620; -} - -.leaflet-fmHighlightShadow-pane { - z-index: 619; -} \ No newline at end of file diff --git a/frontend/app/map/markers/markers.js b/frontend/app/map/markers/markers.js index 96c06ff1..394cdae2 100644 --- a/frontend/app/map/markers/markers.js +++ b/frontend/app/map/markers/markers.js @@ -3,7 +3,7 @@ import $ from 'jquery'; import L from 'leaflet'; import ng from 'angular'; -fm.app.factory("fmMapMarkers", function($uibModal, fmUtils, $compile, $timeout, $rootScope) { +fm.app.factory("fmMapMarkers", function($uibModal, fmUtils, $compile, $timeout, $rootScope, fmHighlightableLayers) { return function(map) { var markersById = { }; let openMarker; @@ -30,9 +30,7 @@ fm.app.factory("fmMapMarkers", function($uibModal, fmUtils, $compile, $timeout, var markersUi = { _addMarker : function(marker) { if(!markersById[marker.id]) { - markersById[marker.id] = L.marker([ 0, 0 ], { - icon: fmUtils.createMarkerIcon(marker.colour, marker.size, marker.symbol, marker.shape) - }).addTo(map.markerCluster) + markersById[marker.id] = (new fmHighlightableLayers.Marker([ 0, 0 ])).addTo(map.markerCluster) .on("click", function(e) { markersUi.showMarkerInfoBox(map.client.markers[marker.id] || marker); }.fmWrapApply($rootScope)) @@ -44,8 +42,13 @@ fm.app.factory("fmMapMarkers", function($uibModal, fmUtils, $compile, $timeout, markersById[marker.id] .setLatLng([ marker.lat, marker.lon ]) - .setIcon(fmUtils.createMarkerIcon(marker.colour, marker.size, marker.symbol, marker.shape, null, openMarker && openMarker.id == marker.id)) - .setOpacity(0.7); + .setStyle({ + colour: marker.colour, + size: marker.size, + symbol: marker.symbol, + shape: marker.shape, + highlight: openMarker && openMarker.id == marker.id + }); if(openMarker && openMarker.id == marker.id) markersUi.showMarkerInfoBox(marker); @@ -91,11 +94,9 @@ fm.app.factory("fmMapMarkers", function($uibModal, fmUtils, $compile, $timeout, openMarker = null; if(markersById[marker.id]) { - markersById[marker.id].remove(); - markersById[marker.id].options.pane = "markerPane"; - markersById[marker.id].setIcon(fmUtils.createMarkerIcon(marker.colour, marker.size, marker.symbol, marker.shape)); - markersById[marker.id].setOpacity(0.7); - markersById[marker.id].addTo(map.map); + markersById[marker.id].setStyle({ + highlight: false + }); } scope.$destroy(); @@ -103,11 +104,9 @@ fm.app.factory("fmMapMarkers", function($uibModal, fmUtils, $compile, $timeout, id: marker.id }; - markersById[marker.id].remove(); - markersById[marker.id].options.pane = "fmHighlightMarkerPane"; - markersById[marker.id].setIcon(fmUtils.createMarkerIcon(marker.colour, marker.size, marker.symbol, marker.shape, null, true)); - markersById[marker.id].setOpacity(1); - markersById[marker.id].addTo(map.map); + markersById[marker.id].setStyle({ + highlight: true + }); }, editMarker: function(marker) { var scope = $rootScope.$new(); diff --git a/frontend/app/map/route/route.js b/frontend/app/map/route/route.js index 1015baaa..1d350557 100644 --- a/frontend/app/map/route/route.js +++ b/frontend/app/map/route/route.js @@ -5,7 +5,7 @@ import ng from 'angular'; import 'leaflet.elevation'; import {saveAs} from 'file-saver'; -fm.app.factory("fmMapRoute", function(fmUtils, $uibModal, $compile, $timeout, $rootScope) { +fm.app.factory("fmMapRoute", function(fmUtils, $uibModal, $compile, $timeout, $rootScope, fmHighlightableLayers) { return function(map) { var dragTimeout = 300; @@ -16,7 +16,6 @@ fm.app.factory("fmMapRoute", function(fmUtils, $uibModal, $compile, $timeout, $r }); let routeLayer = null; - let highlightLayer = null; let dragMarker = null; let markers = [ ]; let dragging = false; @@ -50,34 +49,14 @@ fm.app.factory("fmMapRoute", function(fmUtils, $uibModal, $compile, $timeout, $r // has not been received. let splitLatLngs = fmUtils.disconnectSegmentsOutsideViewport(trackPoints, map.map.getBounds()); - highlightLayer = L.polyline(splitLatLngs, { - pane: "fmHighlightShadowPane", - interactive: false, - color : '#000000', - weight : 10, - opacity : 1 - }).on("click", function(e) { - routeUi.showRouteInfoBox(); - }.fmWrapApply($rootScope)); - - routeLayer = L.polyline(splitLatLngs, { - pane: "fmHighlightPane", + routeLayer = (new fmHighlightableLayers.Polyline(splitLatLngs, { color : '#0000ff', weight : 5, - opacity : 0.5 - }).addTo(map.map).on("click", function(e) { + highlight: !!openInfoBox + })).addTo(map.map).on("click", function(e) { routeUi.showRouteInfoBox(); }.fmWrapApply($rootScope)); - if (openInfoBox) { - highlightLayer.addTo(map.map); - routeLayer.setStyle({ - opacity: 1 - }); - } - - map.map.almostOver.addLayer(routeLayer); - dragMarker = fmUtils.temporaryDragMarker(map.map, routeLayer, map.dragMarkerColour, function(marker) { dragging = true; @@ -154,16 +133,10 @@ fm.app.factory("fmMapRoute", function(fmUtils, $uibModal, $compile, $timeout, $r function clearRoute() { if(routeLayer) { - map.map.almostOver.removeLayer(routeLayer); routeLayer.remove(); routeLayer = null; } - if(highlightLayer) { - highlightLayer.remove(); - highlightLayer = null; - } - if(dragMarker) { dragMarker(); dragMarker = null; @@ -221,20 +194,17 @@ fm.app.factory("fmMapRoute", function(fmUtils, $uibModal, $compile, $timeout, $r let template = $(require("./view-route.html")); - highlightLayer.addTo(map.map); routeLayer.setStyle({ - opacity: 1 + highlight: true }); openInfoBox = map.infoBox.show(template, scope, () => { scope.$destroy(); openInfoBox = null; - if(highlightLayer) - highlightLayer.remove(); if(routeLayer) { routeLayer.setStyle({ - opacity: 0.5 + highlight: false }); } }); diff --git a/frontend/app/search/search-query.js b/frontend/app/search/search-query.js index 01711be5..5e5b53f8 100644 --- a/frontend/app/search/search-query.js +++ b/frontend/app/search/search-query.js @@ -6,7 +6,7 @@ import 'jquery-ui'; import 'jquery-ui/ui/widgets/resizable'; import css from './search-query.scss'; -fm.app.directive("fmSearchQuery", function($rootScope, $compile, fmUtils, $timeout, $q, fmSearchFiles, fmSearchImport) { +fm.app.directive("fmSearchQuery", function($rootScope, $compile, fmUtils, $timeout, $q, fmSearchFiles, fmSearchImport, fmHighlightableLayers) { return { require: "^fmSearch", scope: true, @@ -270,25 +270,20 @@ fm.app.directive("fmSearchQuery", function($rootScope, $compile, fmUtils, $timeo result.layer.remove(); result.layer = null; } - if(result.highlightLayer) { - result.highlightLayer.remove(); - result.highlightLayer = null; - } if(result.marker) { result.marker.remove(); result.marker = null; } if(!result.lat || !result.lon || (result.geojson && result.geojson.type != "Point")) { // If the geojson is just a point, we already render our own marker - result.layer = L.geoJson(result.geojson, { - pane: highlight ? "fmHighlightPane" : "overlayPane", - pointToLayer: function(geoJsonPoint, latlng) { - return L.marker(latlng, { - icon: fmUtils.createMarkerIcon("ff0000", 35, null, null, null, highlight), - pane: highlight ? "fmHighlightMarkerPane" : "markerPane" - }); + result.layer = (new fmHighlightableLayers.GeoJSON(result.geojson, { + highlight, + markerOptions: { + colour: "ff0000", + size: 35, + highlight } - }) + })) .on("click", function(e) { renderResult(query, results, result, true, layerGroup, onOpen, onClose, true); onOpen && onOpen(); @@ -296,36 +291,15 @@ fm.app.directive("fmSearchQuery", function($rootScope, $compile, fmUtils, $timeo .bindTooltip(result.display_name, $.extend({}, map.tooltipOptions, { sticky: true, offset: [ 20, 0 ] })); layerGroup.addLayer(result.layer); - - if(highlight) { - result.highlightLayer = L.geoJson(result.geojson, { - pane: "fmHighlightShadowPane", - pointToLayer: function(geoJsonPoint, latlng) { - return L.marker(latlng, { - icon: fmUtils.createMarkerIcon("ff0000", 35, null, null, null, highlight), - pane: highlight ? "fmHighlightMarkerPane" : "markerPane" - }); - }, - style: (feature) => ({ - color: '#000000', - fill: false, - weight: 6 - }) - }) - .on("click", function(e) { - renderResult(query, results, result, true, layerGroup, onOpen, onClose, true); - onOpen && onOpen(); - }.fmWrapApply($rootScope)); - - layerGroup.addLayer(result.highlightLayer); - } } if(result.lat != null && result.lon != null) { - result.marker = L.marker([ result.lat, result.lon ], { - pane: highlight ? "fmHighlightMarkerPane" : "markerPane", - icon: fmUtils.createMarkerIcon(map.searchMarkerColour, 35, result.icon, null, null, highlight) - }) + result.marker = (new fmHighlightableLayers.Marker([ result.lat, result.lon ], { + highlight, + colour: map.searchMarkerColour, + size: 35, + symbol: result.icon + })) .on("click", function(e) { renderResult(query, results, result, true, layerGroup, onOpen, onClose, true); onOpen && onOpen(); diff --git a/frontend/app/utils/utils.js b/frontend/app/utils/utils.js index 0adb9b9e..ae8d6c1c 100644 --- a/frontend/app/utils/utils.js +++ b/frontend/app/utils/utils.js @@ -3,7 +3,6 @@ import $ from 'jquery'; import L from 'leaflet'; import ng from 'angular'; import 'leaflet-geometryutil'; -import 'leaflet-almostover'; import linkifyStr from 'linkifyjs/string'; import Clipboard from 'clipboard'; import SimpleGraticule from 'leaflet-simple-graticule'; @@ -319,7 +318,7 @@ fm.app.factory("fmUtils", function($parse, fmIcons) { temporaryHoverMarker.remove(); } - line.on("fm-almostover", _over).on("fm-almostmove", _move).on("fm-almostout", _out); + line.on("mouseover", _over).on("mousemove", _move).on("mouseout", _out); function makeTemporaryHoverMarker() { temporaryHoverMarker = L.marker([0,0], Object.assign({ @@ -341,7 +340,7 @@ fm.app.factory("fmUtils", function($parse, fmIcons) { makeTemporaryHoverMarker(); return function() { - line.off("fm-almostover", _over).off("fm-almostmove", _move).off("fm-almostout", _out); + line.off("mouseover", _over).off("mousemove", _move).off("mouseout", _out); temporaryHoverMarker.remove(); }; };