Skip to content

Commit

Permalink
finish DivIcons
Browse files Browse the repository at this point in the history
  • Loading branch information
trafficonese committed Aug 31, 2024
1 parent 6d51de8 commit 311d731
Show file tree
Hide file tree
Showing 7 changed files with 479 additions and 170 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Fix for roxygen2 > 7.0.0. #1491
* The opened sidebar tab is returned as Shiny input using the `sidebar_tabs` ID.
* allow `...` in `antpathOptions` to be able to set the pane (e.g.: `renderer= JS('L.svg({pane: "my-pane"})')`)
* New Function `addDivicon` adds `DivIcon` markers to Leaflet maps with support for custom HTML and CSS classes. See the example in `./inst/examples/divicons_html_app.R`

# leaflet.extras2 1.2.2

Expand Down
76 changes: 58 additions & 18 deletions R/divicon.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,81 @@ diviconDependency <- function() {
)
}

#' Add DivIcon
#' Add DivIcon Markers to a Leaflet Map
#'
#' The function expects either line or point data as spatial data or as Simple Feature.
#' Alternatively, coordinates can also be passed as numeric vectors.
#' @param map the map to add moving markers
#' Adds customizable DivIcon markers to a Leaflet map. The function can accept either spatial
#' data (lines or points) in the form of a Simple Feature (sf) object or numeric vectors
#' for latitude and longitude coordinates. It allows for the application of custom HTML
#' content and CSS classes to each marker, providing high flexibility in marker design.
#'
#' @param map The Leaflet map object to which the DivIcon markers will be added.
#' @inheritParams leaflet::addAwesomeMarkers
#' @param classes A single or vector of CSS-classes
#' @param htmls A single or vector of HTML objects
#' @param options a list of extra options for markers. See
#' \code{\link[leaflet]{markerOptions}}
#' @family Divicon Functions
#' @references \url{https://github.com/ewoken/Leaflet.MovingMarker}
#' @inherit leaflet::addMarkers return
#' @param className A single CSS class or a vector of CSS classes to apply to the DivIcon markers.
#' @param html A single HTML string or a vector of HTML strings to display within the DivIcon markers.
#' @param divOptions A list of extra options for Leaflet DivIcon.
#' @param options A list of extra options for the markers.
#' See \code{\link[leaflet]{markerOptions}} for more details.
#' @family DivIcon Functions
#' @return The modified Leaflet map object.
#' @export
#' @examples
#' library(sf)
#' library(leaflet)
#' library(leaflet.extras2)
#'
#' # Sample data
#' df <- sf::st_as_sf(atlStorms2005)
#' df <- suppressWarnings(st_cast(df, "POINT"))
#' df <- df[sample(1:nrow(df), 50, replace = FALSE),]
#' df$classes = sample(x = c("myclass1","myclass2","myclass3"), nrow(df), replace = TRUE)
#' df$ID <- paste0("ID_", 1:nrow(df))
#'
#' leaflet() %>%
#' addTiles() %>%
#' addDivicon(data = df
#' , html = ~paste0(
#' '<div class="custom-html">',
#' '<div class="title">', Name, '</div>',
#' '<div class="subtitle">MaxWind: ', MaxWind, '</div>',
#' '</div>'
#' )
#' , label = ~Name
#' , layerId = ~ID
#' , group = "Divicons"
#' , popup = ~paste("ID: ", ID, "<br>",
#' "Name: ", Name, "<br>",
#' "MaxWind:", MaxWind, "<br>",
#' "MinPress:", MinPress)
#' , options = markerOptions(draggable = TRUE)
#' )
addDivicon <- function (map, lng = NULL, lat = NULL, layerId = NULL, group = NULL,
icon = NULL, popup = NULL, popupOptions = NULL, label = NULL,
popup = NULL, popupOptions = NULL, label = NULL,
labelOptions = NULL,
classes = NULL, htmls = NULL,
className = NULL, html = NULL,
options = markerOptions(), clusterOptions = NULL,
clusterId = NULL, data = getMapData(map)) {
clusterId = NULL, divOptions = list(), data = getMapData(map)) {
if (missing(labelOptions))
labelOptions <- labelOptions()

map$dependencies <- c(map$dependencies,
diviconDependency())
if (!is.null(clusterOptions))
map$dependencies <- c(map$dependencies, leafletDependencies$markerCluster())

pts <- derivePoints(data, lng, lat, missing(lng), missing(lat),
"addDivicon")
invokeMethod(map, data, "addDivicon", pts$lat, pts$lng,
icon, layerId, group, options,
classes, htmls,
layerId, group, options,
className, html,
popup, popupOptions,
label, labelOptions,
clusterId, clusterOptions) %>%
clusterId, clusterOptions,
divOptions,
getCrosstalkOptions(data)) %>%
expandLimits(pts$lat, pts$lng)
}


getCrosstalkOptions <- utils::getFromNamespace("getCrosstalkOptions", "leaflet")



47 changes: 20 additions & 27 deletions inst/examples/divicons_app.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,6 @@ library(leaflet)
library(leaflet.extras2)
# options("shiny.autoreload" = TRUE)

shipIcon <- leaflet::makeIcon(
iconUrl = "./icons/Icon5.svg"
,className = "lsaicons"
,iconWidth = 24, iconHeight = 24, iconAnchorX = 0, iconAnchorY = 0
)
# shipIcon <- iconList(
# "Schwer" = makeIcon("./icons/Icon5.svg", iconWidth = 32, iconHeight = 32),
# "Mäßig" = makeIcon("./icons/Icon8.svg", iconWidth = 32, iconHeight = 32),
# "Leicht" = makeIcon("./icons/Icon25.svg", iconWidth = 32, iconHeight = 32),
# "kein Schaden" = makeIcon("./icons/Icon29.svg", iconWidth = 32, iconHeight = 32)
# )
# shipIcon <- makeIcon(
# iconUrl = "https://cdn-icons-png.flaticon.com/512/1355/1355883.png",
# iconWidth = 40, iconHeight = 50,
# iconAnchorX = 0, iconAnchorY = 0
# )

df <- sf::st_as_sf(atlStorms2005)
df <- suppressWarnings(st_cast(df, "POINT"))
df <- df[sample(1:nrow(df), 50, replace = F),]
Expand Down Expand Up @@ -63,18 +46,28 @@ server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
addDivicon(data = df,
html = ~Name,
class=~paste("globalclass", classes),
label=~Name,
layerId = ~ID,
icon = shipIcon,
popup=~paste("ID: ", ID, "<br>",
addMarkers(data = df, group="normalmarker",
clusterId = "someclusterid2",
clusterOptions = markerClusterOptions()) %>%
addDivicon(data = df
, html = ~Name
, className = ~paste("globalclass", classes)
, label = ~Name
, layerId = ~ID
, group = "Divicons"
, popup = ~paste("ID: ", ID, "<br>",
"Name: ", Name, "<br>",
"MaxWind:", MaxWind, "<br>",
"MinPress:", MinPress),
options = markerOptions(draggable = TRUE)
)
"MinPress:", MinPress)
, options = markerOptions(draggable = TRUE)
, divOptions = list(
popupAnchor = c(10, 0),
iconSize = 10)
# , clusterId = "someclusterid"
# , clusterOptions = markerClusterOptions()
) %>%
hideGroup("normalmarker") %>%
addLayersControl(overlayGroups = c("Divicons","normalmarker"))
})
output$click <- renderPrint({input$map_marker_click})
output$mouseover <- renderPrint({input$map_marker_mouseover})
Expand Down
118 changes: 118 additions & 0 deletions inst/examples/divicons_html_app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
library(sf)
library(shiny)
library(leaflet)
library(leaflet.extras2)

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

## UI ##################
ui <- fluidPage(
## CSS-style ############
tags$head(tags$style("
.globalclass {
width: 80px !important;
height: 80px !important;
margin-top: -40px !important;
margin-left: -40px !important;
font-size: 12px;
text-align: center;
border-radius: 50%;
color: black;
padding: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.myclass1 {
background-color: #FF5733;
}
.myclass2 {
background-color: #33FF57;
}
.myclass3 {
background-color: #3357FF;
}
.custom-html {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.custom-html img {
border-radius: 50%;
width: 20px;
height: 20px;
margin-bottom: 5px;
}
.custom-html .title {
font-weight: bold;
}
.custom-html .subtitle {
font-size: 10px;
}
")),
## CSS-style END ############
leafletOutput("map", height = 600),
splitLayout(cellWidths = paste0(rep(20,4), "%"),
div(h4("Click Event"), verbatimTextOutput("click")),
div(h4("Mouseover Event"), verbatimTextOutput("mouseover")),
div(h4("Mouseout Event"), verbatimTextOutput("mouseout")),
div(h4("Dragend Event"), verbatimTextOutput("dragend"))
)
)

## SERVER ##################
server <- function(input, output, session) {
# Function to get image URL based on class
getImageUrls <- function(classes) {
urls <- c(
"myclass1" = "https://cdn-icons-png.flaticon.com/512/1355/1355883.png",
"myclass2" = "https://cdn-icons-png.flaticon.com/512/1356/1356623.png",
"myclass3" = "https://cdn-icons-png.flaticon.com/512/1357/1357674.png"
)
return(urls[classes])
}

output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
# addMarkers(data = df, group="normalmarker",
# clusterId = "someclusterid2",
# clusterOptions = markerClusterOptions()) %>%
addDivicon(data = df
, html = ~paste0(
'<div class="custom-html">',
'<img src="', getImageUrls(classes), '">',
'<div class="title">', Name, '</div>',
'<div class="subtitle">MaxWind: ', MaxWind, '</div>',
'</div>'
)
, className = ~paste("globalclass", classes)
, label = ~Name
, layerId = ~ID
, group = "Divicons"
, popup = ~paste("ID: ", ID, "<br>",
"Name: ", Name, "<br>",
"MaxWind:", MaxWind, "<br>",
"MinPress:", MinPress)
, options = markerOptions(draggable = TRUE)
# , clusterId = "someclusterid"
# , clusterOptions = markerClusterOptions()
) %>%
addLabelgun("Divicons", 1) %>%
hideGroup("normalmarker") %>%
addLayersControl(overlayGroups = c("Divicons","normalmarker"))
})
output$click <- renderPrint({input$map_marker_click})
output$mouseover <- renderPrint({input$map_marker_mouseover})
output$mouseout <- renderPrint({input$map_marker_mouseout})
output$dragend <- renderPrint({input$map_marker_dragend})
}

shinyApp(ui, server)
Loading

0 comments on commit 311d731

Please sign in to comment.