I am trying to reproduce this simple plotly graph that shows images on datapoint hover. The code is available here.
However, I am failing to reproduce it. This is what I have so far:
library(htmlwidgets)
library(magrittr)
library(plotly)
js <- "
function(el) {
var tooltip = Plotly.d3.select('#' + el.id + ' .svg-container')
.append(\"div\")
.attr(\"class\", \"my-custom-tooltip\");
el.on('plotly_hover', function(d) {
var pt = d.points[0];
// Choose a location (on the data scale) to place the image
// Here I'm picking the top-left corner of the graph
var x = pt.xaxis.range[0];
var y = pt.yaxis.range[1];
// Transform the data scale to the pixel scale
var xPixel = pt.xaxis.l2p(x) + pt.xaxis._offset;
var yPixel = pt.yaxis.l2p(y) + pt.yaxis._offset;
// Insert the base64 encoded image
var img = \"<img src='\" + pt.customdata + \"' width=100>\";
tooltip.html(img)
.style(\"position\", \"absolute\")
.style(\"left\", xPixel + \"px\")
.style(\"top\", yPixel + \"px\");
// Fade in the image
tooltip.transition()
.duration(300)
.style(\"opacity\", 1);
});
el.on('plotly_unhover', function(d) {
// Fade out the image
tooltip.transition()
.duration(500)
.style(\"opacity\", 0);
});
};
"
x <- 1:3
y <- 1:3
artists <- c("Bethoven", "Mozart", "Bach")
image_links <- c(
"https://upload.wikimedia.org/wikipedia/commons/6/6f/Beethoven.jpg",
"https://upload.wikimedia.org/wikipedia/commons/4/47/Croce-Mozart-Detail.jpg",
"https://upload.wikimedia.org/wikipedia/commons/6/6a/Johann_Sebastian_Bach.jpg"
)
# hoverinfo = "none" will hide the plotly.js tooltip, but the
# plotly_hover event will still fire
plot_ly(hoverinfo = "none") %>%
add_text(x = x, y = y, customdata = image_links, text = artists) %>%
htmlwidgets::onRender(js)
Nothing happens on hover and the console is throwing the following error:
htmlwidgets.js:261 Uncaught SyntaxError: Unexpected token ';'
at tryEval (htmlwidgets.js:252:32)
at htmlwidgets.js:236:24
at Array.forEach (<anonymous>)
at forEach (htmlwidgets.js:55:14)
at evalAndRun (htmlwidgets.js:230:7)
at htmlwidgets.js:654:11
at Array.forEach (<anonymous>)
at forEach (htmlwidgets.js:55:14)
at htmlwidgets.js:576:7
at Array.forEach (<anonymous>)
What am I doing wrong here?
Also, would it be possible to display the tooltip (e.g., as defined in text
) while displaying the image on hover?
The 2.0 release of plotly.js dropped d3 as a bundled dependency, so you'll need to bring that in separately now:
library(htmlwidgets)
library(magrittr)
library(plotly)
x <- 1:3
y <- 1:3
artists <- c("Bethoven", "Mozart", "Bach")
image_links <- c(
"https://upload.wikimedia.org/wikipedia/commons/6/6f/Beethoven.jpg",
"https://upload.wikimedia.org/wikipedia/commons/4/47/Croce-Mozart-Detail.jpg",
"https://upload.wikimedia.org/wikipedia/commons/6/6a/Johann_Sebastian_Bach.jpg"
)
d3 <- htmltools::htmlDependency(
"d3", "7.3",
src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/"),
script = "d3.min.js"
)
# hoverinfo = "none" will hide the plotly.js tooltip, but the
# plotly_hover event will still fire
p <- plot_ly(hoverinfo = "none") %>%
add_text(x = x, y = y, customdata = image_links, text = artists) %>%
htmlwidgets::onRender(readLines("hover_tooltip.js"))
p$dependencies <- c(p$dependencies, list(d3))
p
And then you'll need you change Plotly.d3
to d3
in the JavaScript:
// hover_tooltip.js
function(el) {
var tooltip = d3.select('#' + el.id + ' .svg-container')
.append("div")
.attr("class", "my-custom-tooltip");
el.on('plotly_hover', function(d) {
var pt = d.points[0];
// Choose a location (on the data scale) to place the image
// Here I'm picking the top-left corner of the graph
var x = pt.xaxis.range[0];
var y = pt.yaxis.range[1];
// Transform the data scale to the pixel scale
var xPixel = pt.xaxis.l2p(x) + pt.xaxis._offset;
var yPixel = pt.yaxis.l2p(y) + pt.yaxis._offset;
// Insert the base64 encoded image
var img = "<img src='" + pt.customdata + "' width=100>";
tooltip.html(img)
.style("position", "absolute")
.style("left", xPixel + "px")
.style("top", yPixel + "px");
// Fade in the image
tooltip.transition()
.duration(300)
.style("opacity", 1);
});
el.on('plotly_unhover', function(d) {
// Fade out the image
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With