Skip to content

Commit

Permalink
ha this works.. needs the rbush version 1.4.3
Browse files Browse the repository at this point in the history
  • Loading branch information
trafficonese committed Sep 1, 2024
1 parent c339ebd commit 5f12b1e
Show file tree
Hide file tree
Showing 8 changed files with 809 additions and 118 deletions.
17 changes: 12 additions & 5 deletions R/layergroupcollision.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ layergroupCollisionDependency <- function() {
#'
#' @name LayerroupCollision
addLayerGroupCollision <- function(
map, lng = NULL, lat = NULL, layerId = NULL, group = NULL,
map, layerId = NULL, group = NULL,
popup = NULL, popupOptions = NULL, label = NULL,
labelOptions = NULL,
className = NULL, html = NULL,
Expand All @@ -31,20 +31,27 @@ addLayerGroupCollision <- function(

map$dependencies <- c(map$dependencies, layergroupCollisionDependency())

## Make Geojson ###########
if (!inherits(data, "sf")) {
data <- sf::st_as_sf(data)
}
geojson <- yyjsonr::write_geojson_str(data)
class(geojson) <- c("geojson", "json")

## Derive Points and Invoke Method ##################
pts <- derivePoints(
data, lng, lat, missing(lng), missing(lat),
data, NULL, NULL, TRUE, TRUE,
"addLayerGroupCollision"
)
invokeMethod(
map, data, "addLayerGroupCollision", pts$lat, pts$lng,
map, data, "addLayerGroupCollision", geojson,
layerId, group, options,
className, html,
popup, popupOptions,
label, labelOptions,
clusterId, clusterOptions,
margin,
getCrosstalkOptions(data)
margin
# getCrosstalkOptions(data)
) %>%
expandLimits(pts$lat, pts$lng)
}
66 changes: 57 additions & 9 deletions inst/examples/layergroupcollision_app.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,74 @@ library(shiny)
library(leaflet)
library(sf)
library(leaflet.extras2)
options("shiny.autoreload" = TRUE)

# data <- sf::st_as_sf(breweries91)
data <- sf::st_as_sf(mapview::trails[1:100,])
data <- st_transform(data, 4326)
data <- st_cast(data, "POINT")
data <- data[1:300,]
# data <- sf::st_as_sf(mapview::trails[1:100,])
# data <- st_transform(data, 4326)
# data <- st_cast(data, "POINT")
# data <- data[1:300,]

df <- sf::st_as_sf(atlStorms2005)
df <- suppressWarnings(st_cast(df, "POINT"))
df <- df[sample(1:nrow(df), 150, replace = F),]
# df$classes = sample(x = c("myclass1","myclass2","myclass3"), nrow(df), replace = TRUE)
df$classes = sample(x = 1:5, nrow(df), replace = TRUE)
df$ID <- paste0("ID_", 1:nrow(df))
df$scalerank <- sample(x = 1:5, nrow(df), replace = TRUE)

ui <- fluidPage(
## CSS-style ############
tags$head(tags$style("
.city-label {
background: white;
border: 1px solid #888;
position: relative;
display: inline-block;
white-space: nowrap;
}
.city-label-0 { font-size: 20px; top: -27px; }
.city-label-1 { font-size: 19px; top: -26px; }
.city-label-2 { font-size: 18px; top: -25px; }
.city-label-3 { font-size: 17px; top: -24px; }
.city-label-4 { font-size: 16px; top: -23px; }
.city-label-5 { font-size: 15px; top: -22px; }
.city-label-6 { font-size: 14px; top: -21px; }
.city-label-7 { font-size: 13px; top: -20px; }
.city-label-8 { font-size: 12px; top: -19px; }
.city-label-9 { font-size: 11px; top: -18px; }
.city-label-10{ font-size: 10px; top: -17px; }
")),
leafletOutput("map", height = 800)
)

server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
leaflet::addLayersControl(overlayGroups = "markers") %>%
addMarkers(data = data
, group = "markers"
, label = ~FGN) %>%
addLayerGroupCollision(group = "markers")
leaflet::addLayersControl(overlayGroups = c("Divicons","markers")) %>%
# addMarkers(data = df, label = ~Name,
# , group = "markers") %>%
addLayerGroupCollision(data = df
, html = ~paste0(
'<div class="custom-html">',
'<div class="title">', Name, '</div>',
'<div class="subtitle">MaxWind: ', MaxWind, '</div>',
'</div>'
)
, className = ~paste0("city-label city-label-", classes)
, label = ~Name
, layerId = ~ID
, group = "Divicons"
, popup = ~paste("ID: ", ID, "<br>",
"Name: ", Name, "<br>",
"MaxWind:", MaxWind, "<br>",
"MinPress:", MinPress)
, options = markerOptions(draggable = TRUE)
)

})
}
shinyApp(ui, server)
Original file line number Diff line number Diff line change
Expand Up @@ -4,90 +4,90 @@ var isMSIE8 = !('getComputedStyle' in window && typeof window.getComputedStyle =

function extensions(parentClass) { return {

initialize: function (arg1, arg2) {
var options;
if (parentClass === L.GeoJSON) {
parentClass.prototype.initialize.call(this, arg1, arg2);
options = arg2;
} else {
parentClass.prototype.initialize.call(this, arg1);
options = arg1;
}
this._originalLayers = [];
this._visibleLayers = [];
this._staticLayers = [];
this._rbush = [];
this._cachedRelativeBoxes = [];
this._margin = options.margin || 0;
this._rbush = null;
},

addLayer: function(layer) {
if ( !('options' in layer) || !('icon' in layer.options)) {
this._staticLayers.push(layer);
parentClass.prototype.addLayer.call(this, layer);
return;
}

this._originalLayers.push(layer);
if (this._map) {
this._maybeAddLayerToRBush( layer );
}
},

removeLayer: function(layer) {
this._rbush.remove(this._cachedRelativeBoxes[layer._leaflet_id]);
delete this._cachedRelativeBoxes[layer._leaflet_id];
parentClass.prototype.removeLayer.call(this,layer);
var i;

i = this._originalLayers.indexOf(layer);
if (i !== -1) { this._originalLayers.splice(i,1); }

i = this._visibleLayers.indexOf(layer);
if (i !== -1) { this._visibleLayers.splice(i,1); }

i = this._staticLayers.indexOf(layer);
if (i !== -1) { this._staticLayers.splice(i,1); }
},

clearLayers: function() {
this._rbush = rbush();
this._originalLayers = [];
this._visibleLayers = [];
this._staticLayers = [];
this._cachedRelativeBoxes = [];
parentClass.prototype.clearLayers.call(this);
},

onAdd: function (map) {
this._map = map;

for (var i in this._staticLayers) {
map.addLayer(this._staticLayers[i]);
}

this._onZoomEnd();
map.on('zoomend', this._onZoomEnd, this);
},

onRemove: function(map) {
for (var i in this._staticLayers) {
map.removeLayer(this._staticLayers[i]);
}
map.off('zoomend', this._onZoomEnd, this);
parentClass.prototype.onRemove.call(this, map);
},

_maybeAddLayerToRBush: function(layer) {

var z = this._map.getZoom();
var bush = this._rbush;

var boxes = this._cachedRelativeBoxes[layer._leaflet_id];
var visible = false;
if (!boxes) {
// Add the layer to the map so it's instantiated on the DOM,
initialize: function (arg1, arg2) {
var options;
if (parentClass === L.GeoJSON) {
parentClass.prototype.initialize.call(this, arg1, arg2);
options = arg2;
} else {
parentClass.prototype.initialize.call(this, arg1);
options = arg1;
}
this._originalLayers = [];
this._visibleLayers = [];
this._staticLayers = [];
this._rbush = [];
this._cachedRelativeBoxes = [];
this._margin = options.margin || 0;
this._rbush = null;
},

addLayer: function(layer) {
if ( !('options' in layer) || !('icon' in layer.options)) {
this._staticLayers.push(layer);
parentClass.prototype.addLayer.call(this, layer);
return;
}

this._originalLayers.push(layer);
if (this._map) {
this._maybeAddLayerToRBush( layer );
}
},

removeLayer: function(layer) {
this._rbush.remove(this._cachedRelativeBoxes[layer._leaflet_id]);
delete this._cachedRelativeBoxes[layer._leaflet_id];
parentClass.prototype.removeLayer.call(this,layer);
var i;

i = this._originalLayers.indexOf(layer);
if (i !== -1) { this._originalLayers.splice(i,1); }

i = this._visibleLayers.indexOf(layer);
if (i !== -1) { this._visibleLayers.splice(i,1); }

i = this._staticLayers.indexOf(layer);
if (i !== -1) { this._staticLayers.splice(i,1); }
},

clearLayers: function() {
this._rbush = rbush();
this._originalLayers = [];
this._visibleLayers = [];
this._staticLayers = [];
this._cachedRelativeBoxes = [];
parentClass.prototype.clearLayers.call(this);
},

onAdd: function (map) {
this._map = map;

for (var i in this._staticLayers) {
map.addLayer(this._staticLayers[i]);
}

this._onZoomEnd();
map.on('zoomend', this._onZoomEnd, this);
},

onRemove: function(map) {
for (var i in this._staticLayers) {
map.removeLayer(this._staticLayers[i]);
}
map.off('zoomend', this._onZoomEnd, this);
parentClass.prototype.onRemove.call(this, map);
},

_maybeAddLayerToRBush: function(layer) {

var z = this._map.getZoom();
var bush = this._rbush;

var boxes = this._cachedRelativeBoxes[layer._leaflet_id];
var visible = false;
if (!boxes) {
// Add the layer to the map so it's instantiated on the DOM,
// in order to fetch its position and size.
parentClass.prototype.addLayer.call(this, layer);
var visible = true;
Expand Down Expand Up @@ -241,3 +241,4 @@ L.featureGroup.collision = function (options) {
L.geoJson.collision = function (geojson, options) {
return new L.GeoJSON.Collision(geojson, options || {});
};

39 changes: 34 additions & 5 deletions inst/htmlwidgets/lfx-layergroupcollision/layergroup-binding.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
/* global LeafletWidget, $, L, Shiny, HTMLWidgets */
LeafletWidget.methods.addLayerGroupCollision = function(
lat, lng, layerId, group, options,
data, layerId, group, options,
className, html,
popup, popupOptions, label, labelOptions,
clusterId, clusterOptions, divOptions,
crosstalkOptions) {

(function() {

var collisionLayer = L.LayerGroup.collision({margin:5});
console.log("collisionLayer"); console.log(collisionLayer)

// Manually parse the GeoJSON and create the L.Markers one by one
// Note that 'cities' is defined in the natural earth data files.
console.log("data"); console.log(data)
for (var i=0; i < data.features.length; i++) {

var feat = data.features[i];
var labelClass = 'city-label city-label-' + feat.properties.scalerank;

// Note that the markers are not interactive because MSIE on a WinPhone will take *ages*
// to run addEventListener() on them.
var marker = L.marker(L.GeoJSON.coordsToLatLng(feat.geometry.coordinates), {
icon: L.divIcon({
html:
"<span class='" + labelClass + "'>" +
feat.properties.Name +
"</span>"
})
,interactive: false // Post-0.7.3
,clickable: false // 0.7.3
});
collisionLayer.addLayer(marker);
}
collisionLayer.addTo(this);

};
/*
(function() {
var collisionLayer = L.LayerGroup.collision({margin:5});
// Make a Dataframe
Expand Down Expand Up @@ -56,7 +86,7 @@ LeafletWidget.methods.addLayerGroupCollision = function(
icon: new L.DivIcon(divIconOptions)
}));
collisionLayer.addLayer(marker);
collisionLayer.addLayer(divmarker);
if (cluster) {
clusterGroup.clusterLayerStore.add(divmarker, thisId);
Expand Down Expand Up @@ -108,5 +138,4 @@ LeafletWidget.methods.addLayerGroupCollision = function(
collisionLayer.addTo(this);
}).call(this);
};

*/
Loading

0 comments on commit 5f12b1e

Please sign in to comment.