【问题标题】:Binding javascript (d3.js) to shiny将 javascript (d3.js) 绑定到闪亮
【发布时间】:2014-12-26 08:24:29
【问题描述】:

首先,我不太熟悉 javascript 及其库 d3.js,但我熟悉 R。使用 Shiny 创建仪表板既有趣又简单(感谢 stackoverflow)。现在我想通过将 d3 元素连接到它来扩展它。

我正在寻找有关如何将 javascript 实际绑定到 Shiny(R 仪表板)的信息源并解释实际发生的情况。

背景: 我在 w3schools 上完成了关于 js 和 jquery 的教程,并使用 Scott Murray 的书(Web 的交互式数据可视化)了解了(一点)d3。我希望这足以让我理解有关如何在 Shiny 网站上构建自定义输入/输出绑定的示例和说明:

http://shiny.rstudio.com/articles/building-inputs.html

但不幸的是,我没有,而且我似乎找不到任何使用最少工作代码的示例。 github 上的许多示例对我来说太复杂了,很可能是因为我对 javascript 的经验很少。以下是使用 javascript 进行自定义输入绑定的示例:

https://github.com/jcheng5/shiny-js-examples/tree/master/input

这是我尝试展开的输入和输出绑定示例:

<script src="http://d3js.org/d3.v3.js"></script>
<script type="text/javascript">
(function(){
  // Probably not idiomatic javascript.

  this.countValue=0;

  // BEGIN: FUNCTION
  updateView = function(message) {

    var svg = d3.select(".d3io").select("svg")

    svg.append("text")
      .transition()
      .attr("x",message[0])
      .attr("y",message[1])
      .text(countValue)
      .each("end",function(){
        if(countValue<100) {
          countValue+=1;
          $(".d3io").trigger("change");
        }
      })
  }
  // END: FUNCTION

  //BEGIN: OUTPUT BINDING
  var d3OutputBinding = new Shiny.OutputBinding();
  $.extend(d3OutputBinding, {
    find: function(scope) {
      return $(scope).find(".d3io");
    },
    renderError: function(el,error) {
      console.log("Foe");
    },
    renderValue: function(el,data) {
      updateView(data);
      console.log("Friend");
    }
  });
  Shiny.outputBindings.register(d3OutputBinding);
  //END: OUTPUT BINDING

  //BEGIN: INPUT BINDING
  var d3InputBinding = new Shiny.InputBinding();
  $.extend(d3InputBinding, {
    find: function(scope) {
      return $(scope).find(".d3io");
    },
    getValue: function(el) {
      return countValue;
    },
    subscribe: function(el, callback) {
      $(el).on("change.d3InputBinding", function(e) {
        callback();
      });
    }
  });
  Shiny.inputBindings.register(d3InputBinding);
 //END: OUTPUT BINDING

})()
</script>

其中“d3io”是 ui 中的一个 div 元素,updateView() 是一个函数。这是用户界面:

#UI
library(shiny)

d3IO <- function(inputoutputID) {
  div(id=inputoutputID,class=inputoutputID,tag("svg","")) #; eerst zat ; erbij, maar werkt blijkbaar ook zonder
}

# Define UI for shiny d3 chatter application
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("D3 Javascript chatter",
              "Demo of how to create D3 I/O and cumulative data transfer"),

  sidebarPanel(
    tags$p("This widget is a demonstration of how to wire shiny direct to javascript, without any input elements."),
    tags$p("Each time a transition ends, the client asks the server for another packet of information, and adds it
            to the existing set"),
    tags$p("I can't claim this is likely to be idiomatic javascript, because I'm a novice, but it allows d3 apps
            to do progressive rendering.  In real use, a more complex request/response protocol will probably be
            required.  -AlexBBrown")
  ),

  mainPanel(
    includeHTML("d3widget.js"),
    d3IO("d3io") #Creates div element that d3 selects
    )
))

这是服务器文件:

# SERVER
library(shiny)
# Define server logic required to respond to d3 requests
shinyServer(function(input, output) {

  # Generate a plot of the requested variable against mpg and only 
  # include outliers if requested
  output$d3io <- reactive(function() {
    if (is.null(input$d3io)) {
      0;
    } else {
      list(rnorm(1)*400+200,rnorm(1)*400+200);
    }
  })
})

具体问题:

1) server.r 似乎获得了名为“d3io”(input$d3io) 的输入,因为这没有在 ui.r 中定义,我推断它必须来自 javascript 文件。它实际上指的是哪个元素?

2) 我无法理解自定义绑定部分:

var d3OutputBinding = new Shiny.OutputBinding();
  $.extend(d3OutputBinding, {
    find: function(scope) {
      return $(scope).find(".d3io");
    },
    renderError: function(el,error) {
      console.log("Foe");
    },
    renderValue: function(el,data) {
      updateView(data);
      console.log("Friend");
    }
  });
  Shiny.outputBindings.register(d3OutputBinding);

我的理解是:

创建一个新的闪亮输出绑定,首先找到类 .d3io(div 元素),如果错误则写入控制台“Foe”(这是特殊代码吗?),如果没有错误则使用函数 updateView 使用数据渲染值(在哪里它是否从那里接收此值?)并写入控制台“朋友”。最后注册输出。

希望大家帮忙!我正在创建一个文档,其中包含“在您不知道任何 javascript 时学习如何将 javascript 实现为闪亮的必要步骤”的步骤,我会喜欢的!:)

干杯, 长

【问题讨论】:

  • +1 on“当你不知道任何 javascript 时,学习如何将 javascript 实现为闪亮的必要步骤”
  • 您是否仍然对如何编写自定义绑定的指南感兴趣,包括。 d3.js?

标签: javascript r d3.js shiny


【解决方案1】:

我将退后一步,假设您想要 D3 能够获得的惊人结果,但不一定与 D3 相关联。基本上,我会回答这个问题:

在您不了解任何 JavaScript 的情况下,学习如何将 JavaScript 实现为 Shiny 的必要步骤是什么?

虽然 D3 非常强大,但它也非常难以掌握 - 即使对于许多对 JavaScript 非常熟悉的人来说也是如此。虽然我喜欢 D3 并且几乎每天都在使用它,但在这种情况下我建议不要使用它。取而代之的是名为Plotly 的库,它在后台使用 D3,但专为科学界和数据科学家构建,因此对 R 社区非常友好。

他们有一个thorough tutorial for connecting to Shiny,甚至有一个ggplot2 converter,如果你已经熟悉这种语法,就像R世界中的许多人一样。除非您的需求非常不寻常,否则 Plotly 可能会像直接在 D3 中编写一样满足您的需求,而且学习曲线更加友好。

【讨论】:

  • Plotly 看起来非常用户友好,很好的建议。而不是创建 D3 图像,我正在寻找如何将 D3.js 绑定到闪亮的答案,以便我可以利用现有的很棒的 D3 图像池(无需实际创建它们),这比 plotly 提供的要好.我更喜欢使用直接来源(雄心勃勃)。
  • @warship 看起来这个问题已经不存在了。 :-/
  • 嗨,克里斯,这里是:stackoverflow.com/questions/34426202/…
  • plotly 的问题是,虽然实现很简单,但它需要渲染的时间有点慢。相比之下,D3.js 比这快得多。现在(因为这个问题已经有 5 年的历史了)有一个名为 R2D3 的包,它可以很容易地将 R 连接到 D3。
【解决方案2】:

您熟悉rCharts package 吗?它可以很好地与 Shiny 配合使用,并且大多数输出​​选项都基于 D3 变体。 Twoexamples。

【讨论】:

    【解决方案3】:

    嗨 Sweetbabyjesus(说起来真有趣)。您有两个问题:

    1) server.r 似乎获得了名为“d3io”(input$d3io) 的输入,因为这没有在 ui.r 中定义,我推断它必须来自 javascript 文件。它实际上指的是哪个元素?

    该短语input$d3io 具有以下组成部分:

    • input 是传递给函数的参数 - 它是一个列表 存储应用中所有小部件的当前值。
    • $ 是成员选择器。
    • d3io 指的是具有该 id 的 div 元素的内容 ('d3IO("d3io")') 在 UI 的主面板中。

    2) 我无法理解自定义绑定部分:

    var d3OutputBinding = new Shiny.OutputBinding();
    

    没错,这会创建一个 Shiny.OutputBinding 的实例并将其赋值给变量 d3OutputBinding。

    $.extend(d3OutputBinding, {
      find: function(scope) {
        return $(scope).find(".d3io");
      },
      renderError: function(el,error) {
        console.log("Foe");
      },
      renderValue: function(el,data) {
        updateView(data);
        console.log("Friend");
      }
    });
    

    此代码使用三个函数扩展 d3OutputBinding 的行为,称为 find、renderError 和 renderValue。 Shiny.OutputBinding 需要这三个函数。

    find 是关键,因为它返回一个元素列表,这些元素应该通过它们的el 参数传递给两个渲染函数。请注意,它返回 css 类为“d3io”的元素 - 与前面提到的 div 相同。

    注意extend()是jQuery javascript库的一个函数,这里的$是jQuery对象的别名。

    Shiny.outputBindings.register(d3OutputBinding);
    

    让 Shiny 知道这个新配置的对象现在应该投入使用。

    干杯,尼克

    【讨论】:

      【解决方案4】:

      工作太忙,一直没机会发。请注意,这是使用 customMessageHandler 的解决方法(并且我没有使用自定义输入/输出绑定)。如下:

      目标:从数据框发送数据,使用customMessageHandler创建一个D3JS树。

      路径:我已成功将 data.frame 格式的数据发送到 d3js 树。单击操作按钮后,它将数据框中的数据更改为 JSON 格式,然后将其发送到创建树的 js 文件。树的数据被硬编码在“server.r”中。

      代码在哪里?在我的github上! https://github.com/SweetBabyJesus/shiny-d3js-simple-binding

      原文:我创建了一个基于 CHAID 的树算法,以从大型数据集中创建洞察。人们可以将他们的 csv 上传到仪表板,然后生成 d3js 树:) 代码有点长,因此我为您将其删减并创建了一个最小的代码示例。

      希望你喜欢。

      干杯, 长

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-15
        • 1970-01-01
        • 2014-09-18
        • 2012-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多