Skip to content

Commit

Permalink
fix merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
walkerke committed Dec 31, 2024
2 parents b7b2fd6 + d77c15d commit 5b2d6c5
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 39 deletions.
4 changes: 4 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ URL: https://walker-data.com/mapgl/
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
<<<<<<< HEAD
RoxygenNote: 7.3.2
=======
RoxygenNote: 7.3.2.9000
>>>>>>> d77c15d4602871d52c138c6d69b5a6dca2ce85f1
Imports:
htmlwidgets,
geojsonsf,
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ export(set_filter)
export(set_fog)
export(set_layout_property)
export(set_paint_property)
export(set_source)
export(set_style)
export(set_terrain)
export(set_tooltip)
export(set_view)
export(step_expr)
import(base64enc)
Expand Down
49 changes: 49 additions & 0 deletions R/shiny.R
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,52 @@ move_layer <- function(proxy, layer_id, before_id = NULL) {
proxy$session$sendCustomMessage(proxy_class, list(id = proxy$id, message = message))
proxy
}

#' Set tooltip on a map layer
#'
#' @param map A map object created by the `mapboxgl` or `maplibre` function, or a proxy object.
#' @param layer The ID of the layer to update.
#' @param tooltip The name of the tooltip to set.
#'
#' @return The updated map object.
#' @export
set_tooltip <- function(map, layer, tooltip) {
if (any(inherits(map, "mapboxgl_proxy"), inherits(map, "maplibre_proxy"))) {
proxy_class <- if (inherits(map, "mapboxgl_proxy")) "mapboxgl-proxy" else "maplibre-proxy"
map$session$sendCustomMessage(proxy_class, list(
id = map$id,
message = list(type = "set_tooltip", layer = layer, tooltip = tooltip)
))
} else {
stop("set_tooltip can only be used with mapboxgl_proxy or maplibre_proxy.")
}
return(map)
}

#' Set source of a map layer
#'
#' @param map A map object created by the `mapboxgl` or `maplibre` function, or a proxy object.
#' @param layer The ID of the layer to update.
#' @param source An sf object (which will be converted to a GeoJSON source).
#'
#' @return The updated map object.
#' @export
set_source <- function(map, layer, source) {
if (any(inherits(map, "mapboxgl_proxy"), inherits(map, "maplibre_proxy"))) {

# Convert sf objects to GeoJSON source
if (inherits(source, "sf")) {
source <- geojsonsf::sf_geojson(sf::st_transform(source, crs = 4326))
}

proxy_class <- if (inherits(map, "mapboxgl_proxy")) "mapboxgl-proxy" else "maplibre-proxy"

map$session$sendCustomMessage(proxy_class, list(
id = map$id,
message = list(type = "set_source", layer = layer, source = source)
))
} else {
stop("set_source can only be used with mapboxgl_proxy or maplibre_proxy.")
}
return(map)
}
191 changes: 152 additions & 39 deletions inst/htmlwidgets/mapboxgl.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
function onMouseMoveTooltip(e, map, tooltipPopup, tooltipProperty) {
map.getCanvas().style.cursor = "pointer";
if (e.features.length > 0) {
const description = e.features[0].properties[tooltipProperty];
tooltipPopup.setLngLat(e.lngLat).setHTML(description).addTo(map);

// Store reference to currently active tooltip
window._activeTooltip = tooltipPopup;
} else {
tooltipPopup.remove();
// If this was the active tooltip, clear the reference
if (window._activeTooltip === tooltipPopup) {
delete window._activeTooltip;
}
}
}

function onMouseLeaveTooltip(map, tooltipPopup) {
map.getCanvas().style.cursor = "";
tooltipPopup.remove();
if (window._activeTooltip === tooltipPopup) {
delete window._activeTooltip;
}
}

HTMLWidgets.widget({
name: "mapboxgl",

Expand Down Expand Up @@ -290,28 +315,30 @@ HTMLWidgets.widget({
closeOnClick: false,
});

map.on("mousemove", layer.id, function (e) {
map.getCanvas().style.cursor =
"pointer";
// Create a reference to the mousemove handler function.
// We need to pass 'e', 'map', 'tooltip', and 'layer.tooltip' to onMouseMoveTooltip.
const mouseMoveHandler = function(e) {
onMouseMoveTooltip(e, map, tooltip, layer.tooltip);
};

if (e.features.length > 0) {
const description =
e.features[0].properties[
layer.tooltip
];
tooltip
.setLngLat(e.lngLat)
.setHTML(description)
.addTo(map);
} else {
tooltip.remove();
}
});
// Create a reference to the mouseleave handler function.
// We need to pass 'map' and 'tooltip' to onMouseLeaveTooltip.
const mouseLeaveHandler = function() {
onMouseLeaveTooltip(map, tooltip);
};

map.on("mouseleave", layer.id, function () {
map.getCanvas().style.cursor = "";
tooltip.remove();
});
// Attach the named handler references, not anonymous functions.
map.on("mousemove", layer.id, mouseMoveHandler);
map.on("mouseleave", layer.id, mouseLeaveHandler);

// Store these handler references so you can remove them later if needed
if (!window._mapboxHandlers) {
window._mapboxHandlers = {};
}
window._mapboxHandlers[layer.id] = {
mousemove: mouseMoveHandler,
mouseleave: mouseLeaveHandler
};
}

// Add hover effect if provided
Expand Down Expand Up @@ -1075,27 +1102,27 @@ if (HTMLWidgets.shinyMode) {
closeOnClick: false,
});

map.on("mousemove", message.layer.id, function (e) {
map.getCanvas().style.cursor = "pointer";
// Define named handler functions:
const mouseMoveHandler = function(e) {
onMouseMoveTooltip(e, map, tooltip, message.layer.tooltip);
};

if (e.features.length > 0) {
const description =
e.features[0].properties[
message.layer.tooltip
];
tooltip
.setLngLat(e.lngLat)
.setHTML(description)
.addTo(map);
} else {
tooltip.remove();
}
});
const mouseLeaveHandler = function() {
onMouseLeaveTooltip(map, tooltip);
};

map.on("mouseleave", message.layer.id, function () {
map.getCanvas().style.cursor = "";
tooltip.remove();
});
// Attach handlers by reference:
map.on("mousemove", message.layer.id, mouseMoveHandler);
map.on("mouseleave", message.layer.id, mouseLeaveHandler);

// Store these handler references for later removal:
if (!window._mapboxHandlers) {
window._mapboxHandlers = {};
}
window._mapboxHandlers[message.layer.id] = {
mousemove: mouseMoveHandler,
mouseleave: mouseLeaveHandler
};
}

// Add hover effect if provided
Expand Down Expand Up @@ -1187,7 +1214,25 @@ if (HTMLWidgets.shinyMode) {
);
}
} else if (message.type === "remove_layer") {
// If there's an active tooltip, remove it first
if (window._activeTooltip) {
window._activeTooltip.remove();
delete window._activeTooltip;
}

if (map.getLayer(message.layer)) {
// Check if we have stored handlers for this layer
if (window._mapboxHandlers && window._mapboxHandlers[message.layer]) {
const handlers = window._mapboxHandlers[message.layer];
if (handlers.mousemove) {
map.off("mousemove", message.layer, handlers.mousemove);
}
if (handlers.mouseleave) {
map.off("mouseleave", message.layer, handlers.mouseleave);
}
// Clean up the reference
delete window._mapboxHandlers[message.layer];
}
map.removeLayer(message.layer);
}
if (map.getSource(message.layer)) {
Expand Down Expand Up @@ -1715,6 +1760,74 @@ if (HTMLWidgets.shinyMode) {
} else {
console.error("Invalid image data:", message);
}
} else if (message.type === "set_tooltip") {
const layerId = message.layer;
const newTooltipProperty = message.tooltip;

// If there's an active tooltip open, remove it first
if (window._activeTooltip) {
window._activeTooltip.remove();
delete window._activeTooltip;
}

// Remove old handlers if any
if (window._mapboxHandlers && window._mapboxHandlers[layerId]) {
const handlers = window._mapboxHandlers[layerId];
if (handlers.mousemove) {
map.off("mousemove", layerId, handlers.mousemove);
}
if (handlers.mouseleave) {
map.off("mouseleave", layerId, handlers.mouseleave);
}
delete window._mapboxHandlers[layerId];
}

// Create a new tooltip popup
const tooltip = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false,
});

// Define new handlers referencing the updated tooltip property
const mouseMoveHandler = function(e) {
onMouseMoveTooltip(e, map, tooltip, newTooltipProperty);
};
const mouseLeaveHandler = function() {
onMouseLeaveTooltip(map, tooltip);
};

// Add the new event handlers
map.on("mousemove", layerId, mouseMoveHandler);
map.on("mouseleave", layerId, mouseLeaveHandler);

// Store these handlers so we can remove/update them in the future
if (!window._mapboxHandlers) {
window._mapboxHandlers = {};
}
window._mapboxHandlers[layerId] = {
mousemove: mouseMoveHandler,
mouseleave: mouseLeaveHandler
};
} else if (message.type === "set_source") {
const layerId = message.layer;
const newData = message.source;
const layerObject = map.getLayer(layerId);

if (!layerObject) {
console.error("Layer not found: ", layerId);
return;
}

const sourceId = layerObject.source;
const sourceObject = map.getSource(sourceId);

if (!sourceObject) {
console.error("Source not found: ", sourceId);
return;
}

// Update the geojson data
sourceObject.setData(newData);
}
}
});
Expand Down
21 changes: 21 additions & 0 deletions man/set_source.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions man/set_tooltip.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5b2d6c5

Please sign in to comment.