Skip to content

Commit 3ed3dd4

Browse files
committed
Have subplot() accumulate images and reposition paper coords, addresses #1332
1 parent 0aa4880 commit 3ed3dd4

File tree

2 files changed

+50
-11
lines changed

2 files changed

+50
-11
lines changed

R/subplots.R

+17-11
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ subplot <- function(..., nrows = 1, widths = NULL, heights = NULL, margin = 0.02
120120
traces <- lapply(plots, "[[", "data")
121121
layouts <- lapply(plots, "[[", "layout")
122122
shapes <- lapply(layouts, "[[", "shapes")
123+
images <- lapply(layouts, "[[", "images")
123124
annotations <- lapply(layouts, function(x) {
124125
# keep non axis title annotations (for rescaling)
125126
axes <- vapply(x$annotations, function(a) identical(a$annotationType, "axis"), logical(1))
@@ -263,11 +264,13 @@ subplot <- function(..., nrows = 1, widths = NULL, heights = NULL, margin = 0.02
263264
# reposition shapes and annotations
264265
annotations <- Map(reposition, annotations, split(domainInfo, seq_along(plots)))
265266
shapes <- Map(reposition, shapes, split(domainInfo, seq_along(plots)))
267+
images <- Map(reposition, images, split(domainInfo, seq_along(plots)))
266268
p$layout$annotations <- Reduce(c, annotations)
267269
p$layout$shapes <- Reduce(c, shapes)
270+
p$layout$images <- Reduce(c, images)
268271
# merge non-axis layout stuff
269272
layouts <- lapply(layouts, function(x) {
270-
x[!grepl("^[x-y]axis|^geo|^mapbox|annotations|shapes", names(x))] %||% list()
273+
x[!grepl("^[x-y]axis|^geo|^mapbox|annotations|shapes|images", names(x))] %||% list()
271274
})
272275
if (which_layout != "merge") {
273276
if (!is.numeric(which_layout)) warning("which_layout must be numeric")
@@ -396,24 +399,27 @@ list2df <- function(x, nms) {
396399
# (useful mostly for repositioning annotations/shapes in subplots)
397400
reposition <- function(obj, domains) {
398401
# we need x and y in order to rescale them!
402+
xdom <- as.numeric(domains[c("xstart", "xend")])
403+
ydom <- as.numeric(domains[c("yend", "ystart")])
404+
399405
for (i in seq_along(obj)) {
400406
o <- obj[[i]]
401-
# TODO: this implementation currently assumes xref/yref == "paper"
402-
# should we support references to axis objects as well?
403-
xs <- if (identical(o$xref, "paper")) c("x", "x0", "x1")
407+
xs <- if (identical(o$xref, "paper")) {
408+
if (is.numeric(o$sizex)) obj[[i]]$sizex <- o$sizex * abs(diff(xdom))
409+
c("x", "x0", "x1")
410+
}
404411
for (j in xs) {
405412
if (is.numeric(o[[j]])) {
406-
obj[[i]][[j]] <- scales::rescale(
407-
o[[j]], as.numeric(domains[c("xstart", "xend")]), from = c(0, 1)
408-
)
413+
obj[[i]][[j]] <- scales::rescale(o[[j]], xdom, from = c(0, 1))
409414
}
410415
}
411-
ys <- if (identical(o$xref, "paper")) c("y", "y0", "y1")
416+
ys <- if (identical(o$yref, "paper")) {
417+
if (is.numeric(o$sizey)) obj[[i]]$sizey <- o$sizey * abs(diff(ydom))
418+
c("y", "y0", "y1")
419+
}
412420
for (j in ys) {
413421
if (is.numeric(o[[j]])) {
414-
obj[[i]][[j]] <- scales::rescale(
415-
o[[j]], as.numeric(domains[c("yend", "ystart")]), from = c(0, 1)
416-
)
422+
obj[[i]][[j]] <- scales::rescale(o[[j]], ydom, from = c(0, 1))
417423
}
418424
}
419425
}

tests/testthat/test-plotly-subplot.R

+33
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,39 @@ test_that("annotation xref/yref are bumped correctly", {
166166
expect_equal(yref2, rep(c("y", "y"), each = 32))
167167
})
168168

169+
test_that("images accumulate and paper coordinates are repositioned", {
170+
171+
r <- as.raster(matrix(hcl(0, 80, seq(50, 80, 10)), nrow = 4, ncol = 5))
172+
173+
# embed the raster as an image
174+
p <- plot_ly(x = 1, y = 1) %>%
175+
layout(
176+
images = list(list(
177+
source = raster2uri(r),
178+
sizing = "fill",
179+
xref = "paper",
180+
yref = "paper",
181+
x = 0,
182+
y = 0,
183+
sizex = 0.5,
184+
sizey = 0.5,
185+
xanchor = "left",
186+
yanchor = "bottom"
187+
))
188+
)
189+
190+
s <- subplot(p, p, nrows = 1, margin = 0.02)
191+
imgs <- plotly_build(s)$x$layout$images
192+
expect_true(imgs[[1]]$x == 0)
193+
expect_true(imgs[[1]]$y == 0)
194+
expect_true(imgs[[1]]$sizex == 0.24)
195+
expect_true(imgs[[1]]$sizey == 0.5)
196+
expect_true(imgs[[2]]$x == 0.52)
197+
expect_true(imgs[[2]]$y == 0)
198+
expect_true(imgs[[2]]$sizex == 0.24)
199+
expect_true(imgs[[2]]$sizey == 0.5)
200+
})
201+
169202

170203

171204
test_that("geo+cartesian behaves", {

0 commit comments

Comments
 (0)