ggflags icon indicating copy to clipboard operation
ggflags copied to clipboard

Render arbitrary sets of icons

Open jimjam-slam opened this issue 8 years ago • 4 comments

A logical extension of this package would be a geom that renders an arbitrary set of icons, specified by supplying a named vector of paths to a scale like:

my_icons = c(
  'soccer' = 'icons/soccer.svg',
  'rugby' = 'icons/rugby.svg',
  'basketball' = 'icons/basketball.svg')

sportevents = ggplot(data) +
  geom_icon(aes(x = longitude, y = latitude, size = interest, icon = sport)) +
  scale_icon(values = my_icons)

This would be similar to the way custom colour scales are implemented. I think this could be done either with rastered PNG icons, building on baptiste/ggflags, or with vector SVG icons if I implemented #1.

jimjam-slam avatar Sep 05 '17 03:09 jimjam-slam

I kind of have something along those lines in egg::geom_custom but it's not on CRAN because it requires a newer ggplot2

baptiste avatar Apr 22 '18 01:04 baptiste

That sounds interesting! is it hosted on GitHub?

jimjam-slam avatar Apr 22 '18 01:04 jimjam-slam

privately – I regularly get sick of random "issues" posted by strangers. The idea is to use list-columns to map grobs (or arbitrary data to draw a grob) as a "data" aesthetic.


#' geom_custom
#'
#' @param mapping mapping
#' @param data data
#' @param inherit.aes inherit.aes
#' @param ... arguments passed to the geom's draw_group method
#'
#' @importFrom gtable gtable_matrix gtable_add_grob gtable_add_cols gtable_add_rows
#' @importFrom grid nullGrob unit grobTree editGrob
#' @importFrom ggplot2 ggproto ggproto_parent layer
#' @return layer
#' @export
#' @examples
#' library(grid)
#' d <- data.frame(x=rep(1:3, 4), f=rep(letters[1:4], each=3))
#' gl <- replicate(4, matrix(sample(palette(), 9, TRUE), 3, 3), FALSE)
#' dummy <- data.frame(f=letters[1:4], data = I(gl))
#'
#' ggplot(d, aes(f,x)) +
#'   facet_wrap(~f)+
#'   theme_bw() +
#'   geom_point()+
#'   geom_custom(data = dummy, aes(data = data, y = 2),
#'               grob_fun = function(x) rasterGrob(x, interpolate = FALSE,
#'                                                 width=unit(1,"cm"),
#'                                                 height=unit(1,"cm")))

geom_custom <- function(mapping = NULL,
                        data = NULL,
                        inherit.aes = TRUE,
                        ...) {
  layer(
    geom = GeomCustom,
    mapping = mapping,
    data = data,
    stat = "identity",
    position = "identity",
    show.legend = FALSE,
    inherit.aes = inherit.aes,
    params = list(...)
  )
}

GeomCustom <- ggproto(
  "GeomCustom",
  Geom,
  setup_data = function(self, data, params) {
    data <- ggproto_parent(Geom, self)$setup_data(data, params)
    data
  },


  draw_group = function(data, panel_scales, coord, grob_fun, fun_params=list()) {
    coords <- coord$transform(data, panel_scales)
    gl <- lapply(
      seq_along(data$data),
      function(i) {
        .g <- do.call(grob_fun, c(list(data$data[[i]]), fun_params))
        grid::editGrob(
          .g,
          x = unit(coords$x[i], "native"),
          y = unit(coords$y[i], "native")
        )
      }
    )
    ggplot2:::ggname("geom_custom", do.call(grobTree, gl))
  },

  required_aes = c("data", "x", "y")
)

baptiste avatar Apr 22 '18 01:04 baptiste

Oh, nice! Yeah, you might've seen over on the other issue, but I was thinking of moving the flags list into a df (especially since it could potentially support multiple "fonts" that way). Not super high priority, though; gotta iron out these SVG rendering issues first.

jimjam-slam avatar Apr 22 '18 04:04 jimjam-slam