我正在尝试构建一个自定义 D3 工具提示,使用来自publish.twitter.com 的复制/粘贴代码来显示推文小部件。
我正在 R 中使用plotly 设置绘图,并希望在单击相应的数据点时显示推文小部件(在此处使用此示例推文)。我已经设法使用here描述的方法来显示图像工具提示,并尝试对其进行调整以显示推文小部件。然而,虽然推文的文本、推文的 Twitter 句柄和日期会在单击时显示,但推文小部件却不会 (。“widgets.js”脚本源在 twitter 的复制/粘贴文本中提供,但似乎失败了,只显示推文文本等。
这是 R 中的一个最小示例:
# Load packages
library(plotly)
library(htmlwidgets)
library(htmltools)
library(magrittr)
# Define text and position
x <- 1
y <- 1
label <- c("Click here for tweet")
# D3 dependency
d3 <-
htmltools::htmlDependency("d3", "7.3",
src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/"),
script = "d3.min.js")
# Define plot, provide .js file with custom tweet tooltip & add D3 dependency
p <- plot_ly() %>%
add_text(x = x, y = y, text = label) %>%
htmlwidgets::onRender(readLines("tweet_tooltip.js"))
p$dependencies <- c(p$dependencies, list(d3))
# Render plot
p
其中“tweet_tooltip.js”包含以下函数:
// tweet_tooltip.js
// Adapted from https://stackoverflow.com/questions/71601216/r-plotly-display-image-on-hover
function(el) {
// Define tooltip
var tooltip = d3.select('#' + el.id + ' .svg-container')
.append("div")
.attr("class", "my-custom-tooltip");
el.on('plotly_click', function(d) {
var pt = d.points[0];
// Choose a location (on the data scale) to place the image: upper left corner
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;
// Define tweet variable with twitter blockquote/script
var tweet = '<blockquote class="twitter-tweet"><p lang="en" dir="ltr">How much is it?</p>— Elon Musk (@elonmusk) <a href="https://twitter.com/elonmusk/status/943902052542849024?ref_src=twsrc%5Etfw">December 21, 2017</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>'
// Add to tooltip & define position
tooltip.html(tweet)
.style("position", "absolute")
.style("left", xPixel + "px")
.style("top", yPixel + "px");
tooltip
});
}
这对我来说仍然显得笨拙(所以可能有更好的答案)。您将无法在 Plotly SVG 中添加 iframe,但您可以使其看起来像您所做的那样。另外,如果你不小心,因为它是一个小部件,就像 Plotly 一样,你会覆盖绘图。
您将不会在 RStudio 的预览窗格中看到 Twitter 小部件。您必须在浏览器中发送绘图。如果您不确定如何操作,请告诉我。
如果您使用我的代码,则不需要
D3
。然而,尽管存在差异,唯一真正改变的是 Twitter 小部件element 的放置位置。我在所有 Plotly 内容之后添加了 tooltip
元素,但仍在包含 Plotly 的 htmlwidget
内。
在此代码中,我没有将
js
代码设为单独的文件,它位于我的 R 脚本中。由于它是在 R 脚本中,因此您会看到诸如 \'
而不是 '
之类的内容,以便 R 知道这些是嵌套引用。如果使用单独的 JS 文件,则不会这样做。例如,在我的代码中创建tooltip
时,您会看到var tooltip = $("<div class=\'my-custom
...在单独的JS脚本中,它将被写为var tooltip = $("<div class='my-custom
...
这是我使用的代码。
plot_ly() %>%
add_text(x = x, y = y, text = label) %>%
htmlwidgets::onRender(
'function(el) {
// Define tooltip
var tooltip = $("<div class=\'my-custom-tooltip\'></div>").insertAfter("#js-plotly-tester");
el.on("plotly_click", function(d) {
var pt = d.points[0];
// Choose a location (on the data scale) to place the image: upper left corner
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;
// Define tweet variable with twitter blockquote/script
var tweet = "<blockquote class=\'twitter-tweet\'><p lang=\'en\' dir=\'ltr\'>How much is it?</p>— Elon Musk (@elonmusk) <a href=\'https://twitter.com/elonmusk/status/943902052542849024?ref_src=twsrc%5Etfw\'>December 21, 2017</a></blockquote> <script async src=\'https://platform.twitter.com/widgets.js\' charset=\'utf-8\'></script>";
// Add to tooltip & define position
tooltip.html(tweet)
.css({position: "absolute", left: xPixel + "px", top: yPixel + "px"});
tooltip
});
}')
触发 Twitter 小部件和它显示之间有轻微的延迟(不到一秒)。