Search code examples
rggplot2plotalpha-transparency

How to have geom_curve display constant transparency in arrow when using alpha


My goal is to create curved lines on a map (connecting points), with an arrow on one side. These lines will be semi-transparent. It seems like the best way to achieve my goal is to use geom_curve (though other ggplot2 solutions would also be great).

As such, say that I have this toy plot:

library(tidyverse)
library(ggplot2)
data <- data.frame(x = 4, y = 20, xend = 7, yend = 15)

ggplot(data) + geom_curve(aes(x = x, y = y, xend = xend, yend = yend),
    arrow = arrow(length = unit(0.17, "npc"), type="closed", angle=20),
    colour = "red",
    linewidth = 5,
    angle = 90, 
    alpha=.2,
    lineend = "butt",
    curvature = -0.4,
) 

This creates: enter image description here

The issue I am facing is that, when using geom_curve with a semi-transparent line, the arrow shows up with different levels of transparency when I want it to be uniform. How can I prevent this?

This question is very closely related to: Alpha aesthetic shows arrow's skeleton instead of plain shape - how to prevent it?, except that it uses geom_curve instead of geom_segment. The brilliant answer (https://stackoverflow.com/a/60587296/2049545) defines a new geometry (geom_arrowbar). Would it be possible to modify this to be used for geom_curve? I will also flag another of the answers that points to geom_gene_arrow (https://stackoverflow.com/a/60655018/2049545) - can this be used with curved lines? Or is there some other solution that would work?


Solution

  • To really do this properly would require writing a new version of curveGrob and a whole new geom.

    Fortunately, someone already has. The unpublished ggarrow package by Teunbrand includes a geom_arrow_curve, so you could do:

    remotes::install_github("teunbrand/ggarrow")
    
    library(ggplot2)
    library(ggarrow)
    
    data <- data.frame(x = 4, y = 20, xend = 7, yend = 15)
    
    ggplot(data) + 
      geom_arrow_curve(aes(x = x, y = y, xend = xend, yend = yend),
                  colour = "red",
                  linewidth = 5,
                  angle = 90, 
                  alpha = 0.2,
                  lineend = "butt",
                  curvature = -0.5)
    

    enter image description here