##' add subview to mainview for ggplot2 objects ##' ##' ##' @title subview ##' @param mainview main view ##' @param subview a ggplot or grob object ##' @param x x position ##' @param y y position ##' @param width width of subview, [0,1] ##' @param height height of subview, [0,1] ##' @return ggplot object ##' @importFrom ggplot2 annotation_custom ##' @importFrom ggplot2 ggplotGrob ##' @importFrom ggplot2 ggplot_build ##' @export ##' @author Guangchuang Yu subview <- function(mainview, subview, x, y, width=.1, height=.1) { message("The subview function will be defunct in next release, please use ggimage::geom_subview() instead.") mapping <- mainview$mapping %>% as.character aes_x <- mapping["x"] aes_y <- mapping["y"] if (is.na(aes_x) || is.na(aes_y)) { obj <- ggplot_build(mainview) xrng <- obj$layout$panel_ranges[[1]]$x.range yrng <- obj$layout$panel_ranges[[1]]$y.range } else { xrng <- mainview$data[, aes_x] %>% range yrng <- mainview$data[, aes_y] %>% range } for (i in seq_along(mainview$layers)) { layer <- mainview$layers[[i]] dd <- layer$data if (is(dd, "data.frame")) { mapping <- as.character(layer$mapping) mn <- names(mapping) if ('x' %in% mn) { aes_x <- mapping["x"] xrng <- c(xrng, layer$data[, aes_x]) } if ('xmin' %in% mn) { aes_x <- mapping["xmin"] xrng <- c(xrng, layer$data[, aes_x]) } if ('xmax' %in% mn) { aes_x <- mapping["xmax"] xrng <- c(xrng, layer$data[, aes_x]) } if ('y' %in% mn) { aes_y <- mapping["y"] yrng <- c(yrng, layer$data[, aes_y]) } if ('ymin' %in% mn) { aes_y <- mapping["ymin"] yrng <- c(yrng, layer$data[, aes_y]) } if ('ymax' %in% mn) { aes_y <- mapping["ymax"] yrng <- c(yrng, layer$data[, aes_y]) } xrng <- range(xrng) yrng <- range(yrng) } } xrng <- diff(xrng) yrng <- diff(yrng) if (!any(class(subview) %in% c("ggplot", "trellis", "grob", "character"))) { stop("subview should be a ggplot or grob object, or an image file...") } if (is(subview, "ggplot")) { sv <- ggplotGrob(subview) } else if (is(subview, "trellis")) { sv <- grid::grid.grabExpr(print(subview)) } else if (is(subview, "grob")) { sv <- subview } else if (file.exists(subview)) { readImage <- get_fun_from_pkg("EBImage", "readImage") sv <- rasterGrob(readImage(subview)) } else { stop("subview should be a ggplot or grob object, or an image file...") } width <- width/2 height <- height/2 mainview + annotation_custom( sv, xmin = x - width*xrng, xmax = x + width*xrng, ymin = y - height*yrng, ymax = y + height*yrng) }