javascript - Mengembalikan nama node dalam Diagram Sankey Networkd3 (R/Shiny)


Saya memiliki diagram Sankey networkd3 di aplikasi R/Shiny saya, yang mengambil data dari koneksi MySQL. Saya sedang mencoba mencari cara untuk 'drill-down' ke dalam grafik - mengklik sebuah node dan ini akan mengembalikan nama node tersebut. Saya kemudian akan menggunakan ini untuk mengirimkan query lain ke DB yang akan mengisi tabel di aplikasi.

Ini yang saya punya -

san <- sankeyNetwork(Links = sanData, Nodes = nodes, Source = "source",
    Target = "target", Value = "value")

Ini memplot grafik yang bekerja dengan baik.

Berikut yang telah saya coba sejauh ini -
Gunakan paket R htmlwidgets, dan jalankan skrip JS berikut menggunakan onRender pada grafik sankey saya.

Pengganti untuk skrip JS:

clickFun <- 'd3.selectAll(".link").on("click",function(d) {alert(d.value);})'

Dalam output sankey saya:
onRender(san, clickFun)

Ini mengembalikan nilai dari tautan sebagai peringatan. Saya mencoba menggunakan ".node" dan d.data.name seperti yang disarankan oleh beberapa contoh lain, tetapi saya tidak pernah bisa membuat ini bekerja dan tidak ada peringatan yang muncul.

Berikut adalah pertanyaan saya:
1. Bagaimana saya bisa mendapatkan nama node dari plot sankey saat diklik mouse?
2. Asumsikan saya telah mencapai hal di atas, bagaimana saya bisa menggunakan nilai yang dikembalikan oleh skrip JS saya dalam aplikasi shiny saya? Saya akan mengganti bagian alert() dengan return(), tetapi saya bingung bagaimana saya bisa menggunakan ini dalam aplikasi server saya.

Jawaban #1

Alasan event klik Anda bekerja pada tautan, tetapi tidak pada node adalah karena node juga memiliki perilaku seret yang terpasang padanya. Cara termudah untuk mengatasinya adalah dengan meniadakan perilaku seret dan kemudian menambahkan perilaku klik, seperti ini...

library(networkD3)
library(htmlwidgets)

URL <- paste0('https://cdn.rawgit.com/christophergandrud/networkD3/',
              'master/JSONdata/energy.json')
energy <- jsonlite::fromJSON(URL)

san <- 
  sankeyNetwork(Links = energy$links, Nodes = energy$nodes, Source = 'source',
              Target = 'target', Value = 'value', NodeID = 'name',
              units = 'TWh', fontSize = 12, nodeWidth = 30)

clickFun <- 
  'function() { 
      d3.selectAll(".node").on("mousedown.drag", null);
      d3.selectAll(".node").on("click",function(d) { alert(d.name); })
   }'

onRender(san, clickFun)

ini adalah contoh yang berfungsi di mana event onclick mengembalikan nama node yang diklik, yang kemudian diteruskan ke fungsi R yang memproses perintah SQL dan mengembalikan hasilnya ke perintah datatable, yang menampilkan tautan yang mengikuti dari node tersebut...

library(shiny)
library(networkD3)
library(DT)
library(sqldf)
library(htmlwidgets)

URL <- paste0('https://cdn.rawgit.com/christophergandrud/networkD3/',
              'master/JSONdata/energy.json')
energy <- jsonlite::fromJSON(URL)

energy$links$name <- energy$nodes$name[energy$links$source + 1]
df <- energy$links

funct <-
  function (n) {
    isp <- sprintf("Select * From df Where df.name='%s';", n)
    isd <- sqldf::sqldf(isp)
    return(isd)
  }

ui <- shinyUI(fluidPage(
  fluidRow(
    column(4, sankeyNetworkOutput("sankey")),
    column(4, DT::dataTableOutput("table"))
  )
))

server <- shinyServer(function(input, output, session) { 
  session$onSessionEnded(stopApp)
  output$sankey <- renderSankeyNetwork({
    san <- 
      sankeyNetwork(Links = energy$links, Nodes = energy$nodes, Source = 'source',
                    Target = 'target', Value = 'value', NodeID = 'name',
                    units = 'TWh', fontSize = 12, nodeWidth = 30)

    clickFun <- 
      'function() { 
          d3.selectAll(".node").on("mousedown.drag", null);
          d3.selectAll(".node").on("click",function(d) { Shiny.onInputChange("id", d.name); });
        }'

    onRender(san, clickFun)
  })

  output$table <- DT::renderDataTable(DT::datatable(funct(input$id)))
})

shinyApp(ui = ui, server = server)