Skip to content

Commit

Permalink
better image alignment. closes #147
Browse files Browse the repository at this point in the history
  • Loading branch information
clauswilke committed Aug 22, 2020
1 parent c13be39 commit c92eb40
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 35 deletions.
64 changes: 43 additions & 21 deletions R/draw.R
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ draw_figure_label <- function(label, position = c("top.left", "top", "top.right"
#' related functions.
#' @param x The x location of the image. (Left side if `hjust = 0`.)
#' @param y The y location of the image. (Bottom side if `vjust = 0`.)
#' @param hjust Horizontal justification relative to x.
#' @param vjust Vertical justification relative to y.
#' @param hjust,vjust Horizontal and vertical justification relative to x.
#' @param halign,valign Horizontal and vertical justification of the image inside
#' the box.
#' @param width Width of the image.
#' @param height Height of the image.
#' @param scale Scales the image relative to the rectangle defined by `x`, `y`, `width`, `height`. A setting
Expand All @@ -272,16 +273,25 @@ draw_figure_label <- function(label, position = c("top.left", "top", "top.right"
#' # Use image as plot background
#' p <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
#' geom_density(alpha = 0.7) +
#' scale_y_continuous(expand = expand_scale(mult = c(0, 0.05))) +
#' scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
#' theme_half_open(12)
#'
#' logo_file <- system.file("extdata", "logo.png", package = "cowplot")
#' ggdraw() +
#' draw_image(logo_file, scale = .7) +
#' draw_image(
#' logo_file, scale = .7
#' ) +
#' draw_plot(p)
#'
#' # Make grid with plot and image
#' # Place in lower right corner
#' ggdraw() +
#' draw_image(
#' logo_file, scale = .3, x = 1,
#' hjust = 1, halign = 1, valign = 0
#' ) +
#' draw_plot(p)
#'
#' # Make grid with plot and image
#' cow_file <- system.file("extdata", "cow.jpg", package = "cowplot")
#' p2 <- ggdraw() + draw_image(cow_file, scale = 0.9)
#' plot_grid(
Expand All @@ -305,7 +315,7 @@ draw_figure_label <- function(label, position = c("top.left", "top", "top.right"
#' }
#' @export
draw_image <- function(image, x = 0, y = 0, width = 1, height = 1, scale = 1, clip = "inherit",
interpolate = TRUE, hjust = 0, vjust = 0) {
interpolate = TRUE, hjust = 0, vjust = 0, halign = 0.5, valign = 0.5) {
if (!requireNamespace("magick", quietly = TRUE)){
warning("Package `magick` is required to draw images. Image not drawn.", call. = FALSE)
draw_grob(grid::nullGrob(), x, y, width, height)
Expand All @@ -319,11 +329,15 @@ draw_image <- function(image, x = 0, y = 0, width = 1, height = 1, scale = 1, cl
else {
image_data <- magick::image_read(image)
}
g <- grid::rasterGrob(image_data, interpolate = interpolate)
g <- grid::rasterGrob(
image_data,
x = halign, y = valign, hjust = halign, vjust = valign,
interpolate = interpolate
)
draw_grob(
g, x = x, y = y, width = width, height = height,
hjust = hjust, vjust = vjust, scale = scale,
clip = clip
clip = clip, halign = halign, valign = valign
)
}
}
Expand All @@ -336,8 +350,9 @@ draw_image <- function(image, x = 0, y = 0, width = 1, height = 1, scale = 1, cl
#' or a recorded base-R plot, as in [as_grob()].
#' @param x The x location of the plot. (Left side if `hjust = 0`.)
#' @param y The y location of the plot. (Bottom side if `vjust = 0`.)
#' @param hjust Horizontal justification relative to x.
#' @param vjust Vertical justification relative to y.
#' @param hjust,vjust Horizontal and vertical justification relative to x.
#' @param halign,valign Horizontal and vertical justification of the plot inside
#' the box.
#' @param width Width of the plot.
#' @param height Height of the plot.
#' @param scale Scales the grob relative to the rectangle defined by `x`, `y`, `width`, `height`. A setting
Expand All @@ -352,11 +367,12 @@ draw_image <- function(image, x = 0, y = 0, width = 1, height = 1, scale = 1, cl
#' ggdraw() + draw_plot(p, .6, .6, .4, .4)
#' @export
draw_plot <- function(plot, x = 0, y = 0, width = 1, height = 1, scale = 1,
hjust = 0, vjust = 0) {
hjust = 0, vjust = 0, halign = 0.5, valign = 0.5) {
plot <- as_grob(plot) # convert to grob if necessary
draw_grob(
plot, x = x, y = y, width = width, height = height,
scale = scale, hjust = hjust, vjust = vjust
scale = scale, hjust = hjust, vjust = vjust,
halign = halign, valign = valign
)
}

Expand All @@ -367,8 +383,9 @@ draw_plot <- function(plot, x = 0, y = 0, width = 1, height = 1, scale = 1,
#' @param grob The grob to place.
#' @param x The x location of the grob. (Left side if `hjust = 0`.)
#' @param y The y location of the grob. (Bottom side if `vjust = 0`.)
#' @param hjust Horizontal justification relative to x.
#' @param vjust Vertical justification relative to y.
#' @param hjust,vjust Horizontal and vertical justification relative to x.
#' @param halign,valign Horizontal and vertical justification of the grob inside
#' the box.
#' @param width Width of the grob.
#' @param height Height of the grob.
#' @param scale Scales the grob relative to the rectangle defined by `x`, `y`, `width`, `height`. A setting
Expand All @@ -382,7 +399,7 @@ draw_plot <- function(plot, x = 0, y = 0, width = 1, height = 1, scale = 1,
#' ggdraw() + draw_grob(g, scale = 0.5)
#' @export
draw_grob <- function(grob, x = 0, y = 0, width = 1, height = 1, scale = 1, clip = "inherit",
hjust = 0, vjust = 0) {
hjust = 0, vjust = 0, halign = 0.5, valign = 0.5) {
layer(
data = data.frame(x = NA),
stat = StatIdentity,
Expand All @@ -396,7 +413,9 @@ draw_grob <- function(grob, x = 0, y = 0, width = 1, height = 1, scale = 1, clip
ymin = y - vjust*height,
ymax = y + (1-vjust)*height,
scale = scale,
clip = clip
clip = clip,
halign = halign,
valign = valign
)
)
}
Expand All @@ -407,7 +426,8 @@ draw_grob <- function(grob, x = 0, y = 0, width = 1, height = 1, scale = 1, clip
#' @importFrom ggplot2 ggproto GeomCustomAnn
#' @export
GeomDrawGrob <- ggproto("GeomDrawGrob", GeomCustomAnn,
draw_panel = function(self, data, panel_params, coord, grob, xmin, xmax, ymin, ymax, scale = 1, clip = "inherit") {
draw_panel = function(self, data, panel_params, coord, grob, xmin, xmax, ymin, ymax, scale = 1, clip = "inherit",
halign = 0.5, valign = 0.5) {
if (!inherits(coord, "CoordCartesian")) {
stop("draw_grob only works with Cartesian coordinates",
call. = FALSE)
Expand All @@ -421,13 +441,15 @@ GeomDrawGrob <- ggproto("GeomDrawGrob", GeomCustomAnn,
# set up inner and outer viewport for clipping. Unfortunately,
# clipping doesn't work properly most of the time, due to
# grid limitations
vp_outer <- grid::viewport(x = mean(x_rng), y = mean(y_rng),
vp_outer <- grid::viewport(x = min(x_rng) + halign*diff(x_rng),
y = min(y_rng) + valign*diff(y_rng),
width = diff(x_rng), height = diff(y_rng),
just = c("center", "center"),
just = c(halign, valign),
clip = clip)

vp_inner <- grid::viewport(width = scale, height = scale,
just = c("center", "center"))
vp_inner <- grid::viewport(x = halign, y = valign,
width = scale, height = scale,
just = c(halign, valign))

id <- annotation_id()
inner_grob <- grid::grobTree(grob, vp = vp_inner, name = paste(grob$name, id))
Expand Down
9 changes: 6 additions & 3 deletions man/draw_grob.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 18 additions & 6 deletions man/draw_image.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions man/draw_plot.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions tests/figs/draw-functions/four-corners-aligned-scaled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions tests/figs/draw-functions/four-corners-centered-scaled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions tests/testthat/test_draw_.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,60 @@ test_that("draw_grob() can align grobs", {
)
})

test_that("image placement and scaling", {
img_src <- system.file("extdata", "logo.png", package = "cowplot")

p <- ggplot() + xlim(0, 1) + ylim(0, 1)

expect_doppelganger(
"four corners, centered, scaled",
p +
draw_image(
img_src, scale = 0.5,
x = 0, y = 0, width = .4, height = .4, hjust = 0, vjust = 0
) +
draw_image(
img_src, scale = 0.75,
x = 1, y = 0, width = .4, height = .4, hjust = 1, vjust = 0
) +
draw_image(
img_src, scale = 1.0,
x = 1, y = 1, width = .4, height = .4, hjust = 1, vjust = 1
) +
draw_image(
img_src, scale = 1.25,
x = 0, y = 1, width = .4, height = .4, hjust = 0, vjust = 1
)
)

expect_doppelganger(
"four corners, aligned, scaled",
p +
draw_image(
img_src, scale = 0.5,
x = 0, y = 0, width = .4, height = .4, hjust = 0, vjust = 0,
halign = 0, valign = 0
) +
draw_image(
img_src, scale = 0.75,
x = 1, y = 0, width = .4, height = .4, hjust = 1, vjust = 0,
halign = 1, valign = 0
) +
draw_image(
img_src, scale = 1.0,
x = 1, y = 1, width = .4, height = .4, hjust = 1, vjust = 1,
halign = 1, valign = 1
) +
draw_image(
img_src, scale = 1.25,
x = 0, y = 1, width = .4, height = .4, hjust = 0, vjust = 1,
halign = 0, valign = 1
)
)
})



test_that("draw_plot_label() works", {
theme_old <- theme_set(
theme_cowplot() +
Expand Down
7 changes: 5 additions & 2 deletions vignettes/drawing_with_on_plots.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,15 @@ ggdraw() +
draw_plot(p)
```

We can also add an image as a logo onto a plot.
We can also add an image as a logo onto a plot. We use `halign` and `valign` in addition to `hjust` and `vjust` to align the image flush in the top right corner.

```{r fig.width = 5.7, fig.height = 3.8}
logo_file <- system.file("extdata", "logo.png", package = "cowplot")
ggdraw() +
draw_plot(p) +
draw_image(logo_file, x = 1, hjust = 1, width = 0.13, height = 0.2)
draw_image(
logo_file, x = 1, y = 1, hjust = 1, vjust = 1, halign = 1, valign = 1,
width = 0.15
)
```

0 comments on commit c92eb40

Please sign in to comment.