English 中文(简体)
Embedding tweets in D3 tooltip
原标题:

I m trying to build a custom D3 tooltip that displays a tweet widget using the copy/paste code from publish.twitter.com.

I m setting up plots using plotly in R and would like a tweet widget to be displayed when clicking on the respective data point (using this example tweet here). I have managed to use the approach described here to display image tooltips and have tried to adapt it to show tweet widgets. However, while the text of the tweet, the twitter handle and date of the tweet are displayed on clicking, the tweet widget is not (Tweet text is displayed, widget isn t.. The widgets.js script source is provided in the copy/paste text from twitter, but seems to fail, leaving only the tweet text etc. to be displayed.

Here is a minimal example in 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

Where tweet_tooltip.js contains the following function:


// 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>&mdash; 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

    });
}


问题回答

This still seems clunky to me (so there is likely a better answer out there). You re not going to be able to add an iframe within the Plotly SVG, but you can make it look like you did. Additionally, if you aren t careful, because it s a widget, as is Plotly, you ll overwrite the plot.

You will not see the Twitter Widget in the preview pane in RStudio. You have to send the plot in your browser. If you re not sure how to do that, let me know.

enter image description here

If you use my code, you don t need D3. However, despite the differences, the only thing that truly changed is where the Twitter widget element is placed. I added the tooltip element after the all Plotly content, but still within the htmlwidget that houses Plotly.

In this code, I didn t make the js code a separate file, it s in my R script. Since it s in an R script you ll see things like instead of so that R knew that these were nested quotations. With a separate JS file, you would not do that. For example, in the creation of tooltip in my code, you ll see var tooltip = $("<div class= my-custom... In a separate JS script, it would be written as var tooltip = $("<div class= my-custom...

Here s the code I used.

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>&mdash; 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
      });
  } )

There is a slight delay between when you trigger the Twitter Widget and when it shows up (less than a second).





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签