I have a very simple plotly graph for which I would like to put the company logos instead (or both) of their names on the Y axis
library(plotly)
plot_ly(
y = c("company_1", "company_2", "company_3", "company_4", "company_5"),
x = c(20, 14, 23, 6, 28),
name = "companies",
type = "bar"
)
For example, we can imagine that the companies are Facebook, Twitter, Apple, Microsoft and Tesla I have images (logo) in png format.
Is there a way to do this?
This isn't something you'll be able to do strictly in R. However, if you use the function onRender
from htmlwidgets
, you can do it.
I added margin
so the images would fit. However, the plot is exactly as you provided it. Make sure that if/when you make changes you respect the whitespace shown here. HTML and Javascript won't understand if the attributes are smashed together.
The first code & plot uses an image that is on the web. The next code & plot uses a local file. That way you can use whichever method applies in your situation.
plot_ly(
y = c("company_1", "company_2", "company_3", "company_4", "company_5"),
x = c(20, 14, 23, 6, 28),
name = "companies",
type = "bar") %>%
layout(margin = list(l = 120, r = 20, t = 20, b = 50)) %>%
htmlwidgets::onRender("function(){
gimme = document.querySelectorAll('g.ytick'); /* get the text positions on y-axis */
imTag1 = '<image width=\"100\" height=\"100\" ' /* pre-build the HTML */
imTag2 = ' href=\"https://www.rstudio.com/wp-content/uploads/2018/10/RStudio-Logo-Flat.png\" />'
for(i = 0; i < gimme.length; i++) {
zz = gimme[i].firstChild.getAttribute('transform'); /* get position on page*/
yy = gimme[i].firstChild.getAttribute('y');
yy = yy * -10;
img = imTag1 + 'x=\"10\" y=\"' + yy + '\" transform=\"' + zz + '\"' + imTag2;
gimme[i].innerHTML = img; /* replace the text tag */
}
}")
The image I used here is from https://www.hiclipart.com/free-transparent-background-png-clipart-qzdon/download
In MY files it's saved at ./_images/orangeIcon.png (where '.' represents the current working directory).
Because this file is a png, I need to make something better for web portability, so I used base64 encoding using the package base64enc
.
img <- base64enc::dataURI(file = "./_images/orangeIcon.png")
I'm going to assign this to customdata
in the call for plotly
. If you had five images, you can make a list of the 5 encoded images. if you list one, plotly
will replicate it. (That's what it did here.)
plot_ly(
y = c("company_1", "company_2", "company_3", "company_4", "company_5"),
x = c(20, 14, 23, 6, 28),
name = "companies", customdata = img, # <---- custom data!!
type = "bar") %>%
layout(margin = list(l = 120, r = 20, t = 20, b = 50)) %>%
htmlwidgets::onRender("function(el, x){ /* changed here, as well */
gimme = document.querySelectorAll('g.ytick'); /* get the text positions on y-axis */
imgs = x.data[0].customdata; /* collect the images */
imTag1 = '<image width=\"100\" height=\"100\" href=\"' /* pre-build the HTML */
imTag2 = ' \" />'
for(i = 0; i < gimme.length; i++) {
zz = gimme[i].firstChild.getAttribute('transform'); /* get position on page*/
yy = gimme[i].firstChild.getAttribute('y');
yy = yy * -10;
img = imTag1 + imgs[i] + '\" x=\"10\" y=\"' + yy + '\" transform=\"' + zz + '\"' + imTag2;
gimme[i].innerHTML = img; /* replace the text tag */
}
}") # note the differences in imgTag1 and imgTag2
# to accommodate the new info for href