From 5cfe70bc886ca61320575c8f587e427bc612690a Mon Sep 17 00:00:00 2001 From: Joe Cheng Date: Sun, 18 Feb 2024 13:13:37 -0800 Subject: [PATCH] Add options to addRasterImage (#692) * Add options to addRasterImage * Use correct options Co-authored-by: Barret Schloerke * Roxygenize * Pass addRasterImage options correctly --------- Co-authored-by: Barret Schloerke --- DESCRIPTION | 2 +- NAMESPACE | 1 + NEWS.md | 2 ++ R/layers.R | 34 ++++++++++++++++++++++++++++-- inst/htmlwidgets/assets/leaflet.js | 8 +++---- javascript/src/methods.js | 8 +++---- man/addRasterImage.Rd | 4 ++++ man/map-options.Rd | 12 +++++++++++ 8 files changed, 58 insertions(+), 13 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 2c7c26976..1d2168122 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -79,4 +79,4 @@ Suggests: Config/testthat/edition: 3 Encoding: UTF-8 LazyData: true -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 diff --git a/NAMESPACE b/NAMESPACE index 195e28f1b..d9a98b3c9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -115,6 +115,7 @@ export(fitBounds) export(flyTo) export(flyToBounds) export(getMapData) +export(gridOptions) export(groupOptions) export(hideGroup) export(highlightOptions) diff --git a/NEWS.md b/NEWS.md index f28302ce8..59574a64e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,8 @@ * Replace viridis dependency by viridisLite (@olivroy, #897) +* `addRasterImage` now takes `options = gridOptions()`, so that arbitrary Leaflet layer options can be controlled. (#692) + # leaflet 2.2.1 * When `addProviderTiles()` is used with `{leaflet.providers}` version 2.0.0 or later, the `leaflet-providers` HTML dependency produced can be correctly cached by knitr. When used with older versions of `{leaflet.providers}`, the HTML dependency uses temp files that break knitr's caching mechanism (thanks @qdread, @jaredlander; #884). diff --git a/R/layers.R b/R/layers.R index 0fb2967d8..d68a9043a 100644 --- a/R/layers.R +++ b/R/layers.R @@ -225,6 +225,8 @@ epsg3857 <- "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y #' Ignored if \code{project = FALSE}. See \code{\link{projectRaster}} for details. #' @param maxBytes the maximum number of bytes to allow for the projected image #' (before base64 encoding); defaults to 4MB. +#' @param options a list of additional options, intended to be provided by +#' a call to \code{\link{gridOptions}} #' @template data-getMapData #' #' @seealso \code{\link{addRasterLegend}} for an easy way to add a legend for a @@ -254,6 +256,7 @@ addRasterImage <- function( project = TRUE, method = c("auto", "bilinear", "ngb"), maxBytes = 4 * 1024 * 1024, + options = gridOptions(), data = getMapData(map) ) { if (inherits(x, "SpatRaster")) { @@ -268,6 +271,7 @@ addRasterImage <- function( project = project, method = method, maxBytes = maxBytes, + options = options, data = data ) } else if (inherits(x, "RasterLayer")) { @@ -282,6 +286,7 @@ addRasterImage <- function( project = project, method = method, maxBytes = maxBytes, + options = options, data = data ) } else { @@ -389,10 +394,14 @@ addRasterImage_RasterLayer <- function( project = TRUE, method = c("auto", "bilinear", "ngb"), maxBytes = 4 * 1024 * 1024, + options = gridOptions(), data = getMapData(map) ) { + options$opacity <- opacity + options$attribution <- attribution + raster_is_factor <- raster::is.factor(x) method <- match.arg(method) if (method == "auto") { @@ -444,7 +453,7 @@ addRasterImage_RasterLayer <- function( list(raster::ymin(bounds), raster::xmax(bounds)) ) - invokeMethod(map, data, "addRasterImage", uri, latlng, opacity, attribution, layerId, group) %>% + invokeMethod(map, data, "addRasterImage", uri, latlng, layerId, group, options) %>% expandLimits( c(raster::ymin(bounds), raster::ymax(bounds)), c(raster::xmin(bounds), raster::xmax(bounds)) @@ -462,6 +471,7 @@ addRasterImage_SpatRaster <- function( project = TRUE, method = c("auto", "bilinear", "ngb"), maxBytes = 4 * 1024 * 1024, + options = gridOptions(), data = getMapData(map) ) { if (!is_installed("terra", "1.6-3")) { # for terra::has.RGB() @@ -471,6 +481,9 @@ addRasterImage_SpatRaster <- function( ) } + options$opacity <- opacity + options$attribution <- attribution + if (terra::has.RGB(x)) { # RGB(A) channels to color table x <- terra::colorize(x, "col") @@ -548,7 +561,7 @@ addRasterImage_SpatRaster <- function( list(terra::ymin(bounds), terra::xmax(bounds)) ) - invokeMethod(map, data, "addRasterImage", uri, latlng, opacity, attribution, layerId, group) %>% + invokeMethod(map, data, "addRasterImage", uri, latlng, layerId, group, options) %>% expandLimits( c(terra::ymin(bounds), terra::ymax(bounds)), c(terra::xmin(bounds), terra::xmax(bounds)) @@ -639,6 +652,23 @@ tileOptions <- function( )) } +#' @describeIn map-options Options for grid layers +#' @export +gridOptions <- function( + tileSize = 256, + updateWhenIdle = NULL, + zIndex = 1, + minZoom = 0, + maxZoom = NULL, + ... +) { + filterNULL(list( + tileSize = tileSize, updateWhenIdle = updateWhenIdle, zIndex = zIndex, + minZoom = minZoom, maxZoom = maxZoom, + ... + )) +} + #' Remove elements from a map #' #' Remove one or more features from a map, identified by \code{layerId}; or, diff --git a/inst/htmlwidgets/assets/leaflet.js b/inst/htmlwidgets/assets/leaflet.js index c8e7e5e0f..79dbe714a 100644 --- a/inst/htmlwidgets/assets/leaflet.js +++ b/inst/htmlwidgets/assets/leaflet.js @@ -2266,7 +2266,7 @@ methods.setGroupOptions = function (group, options) { this.showHideGroupsOnZoom(); }; -methods.addRasterImage = function (uri, bounds, opacity, attribution, layerId, group) { +methods.addRasterImage = function (uri, bounds, layerId, group, options) { // uri is a data URI containing an image. We want to paint this image as a // layer at (top-left) bounds[0] to (bottom-right) bounds[1]. // We can't simply use ImageOverlay, as it uses bilinear scaling which looks @@ -2386,12 +2386,10 @@ methods.addRasterImage = function (uri, bounds, opacity, attribution, layerId, g img.src = uri; - var canvasTiles = _leaflet2["default"].gridLayer({ - opacity: opacity, - attribution: attribution, + var canvasTiles = _leaflet2["default"].gridLayer(Object.assign({}, options, { detectRetina: true, async: true - }); // NOTE: The done() function MUST NOT be invoked until after the current + })); // NOTE: The done() function MUST NOT be invoked until after the current // tick; done() looks in Leaflet's tile cache for the current tile, and // since it's still being constructed, it won't be found. diff --git a/javascript/src/methods.js b/javascript/src/methods.js index 153b1b816..91d8ea70b 100644 --- a/javascript/src/methods.js +++ b/javascript/src/methods.js @@ -983,7 +983,7 @@ methods.setGroupOptions = function(group, options) { this.showHideGroupsOnZoom(); }; -methods.addRasterImage = function(uri, bounds, opacity, attribution, layerId, group) { +methods.addRasterImage = function(uri, bounds, layerId, group, options) { // uri is a data URI containing an image. We want to paint this image as a // layer at (top-left) bounds[0] to (bottom-right) bounds[1]. @@ -1104,12 +1104,10 @@ methods.addRasterImage = function(uri, bounds, opacity, attribution, layerId, gr }; img.src = uri; - let canvasTiles = L.gridLayer({ - opacity: opacity, - attribution: attribution, + let canvasTiles = L.gridLayer(Object.assign({}, options, { detectRetina: true, async: true - }); + })); // NOTE: The done() function MUST NOT be invoked until after the current // tick; done() looks in Leaflet's tile cache for the current tile, and diff --git a/man/addRasterImage.Rd b/man/addRasterImage.Rd index 807f065e5..5f7f87b48 100644 --- a/man/addRasterImage.Rd +++ b/man/addRasterImage.Rd @@ -16,6 +16,7 @@ addRasterImage( project = TRUE, method = c("auto", "bilinear", "ngb"), maxBytes = 4 * 1024 * 1024, + options = gridOptions(), data = getMapData(map) ) @@ -55,6 +56,9 @@ Ignored if \code{project = FALSE}. See \code{\link{projectRaster}} for details.} \item{maxBytes}{the maximum number of bytes to allow for the projected image (before base64 encoding); defaults to 4MB.} +\item{options}{a list of additional options, intended to be provided by +a call to \code{\link{gridOptions}}} + \item{data}{the data object from which the argument values are derived; by default, it is the \code{data} object provided to \code{leaflet()} initially, but can be overridden} diff --git a/man/map-options.Rd b/man/map-options.Rd index de343d5a7..143edbcaa 100644 --- a/man/map-options.Rd +++ b/man/map-options.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/layers.R \name{tileOptions} \alias{tileOptions} +\alias{gridOptions} \alias{WMSTileOptions} \alias{popupOptions} \alias{labelOptions} @@ -29,6 +30,15 @@ tileOptions( ... ) +gridOptions( + tileSize = 256, + updateWhenIdle = NULL, + zIndex = 1, + minZoom = 0, + maxZoom = NULL, + ... +) + WMSTileOptions( styles = "", format = "image/jpeg", @@ -183,6 +193,8 @@ listed in the layer functions. \itemize{ \item \code{tileOptions()}: Options for tile layers +\item \code{gridOptions()}: Options for grid layers + \item \code{WMSTileOptions()}: Options for WMS tile layers \item \code{popupOptions()}: Options for popups