javascript - 将 javascript (d3.js) 绑定(bind)到 shiny

标签 javascript r d3.js shiny

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

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

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

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

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

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

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

<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) 我无法理解自定义绑定(bind)部分:

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);

我的理解是:

创建一个新的 shiny outputbinding,首先找到类 .d3io(div 元素),如果错误则写入控制台“Foe”(这是特殊代码吗?),如果没有错误则使用函数 renderValue updateView 使用数据(Where它从哪里接收到这个值?)并写入控制台“Friend”。最后注册输出。

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

干杯, 长

最佳答案

嗨 Sweetbabyjesus(说起来很有趣)。你有两个问题:

1) The server.r seems to get input called "d3io" (input$d3io) since this is not defined in ui.r, I reasoned it must come from the javascript file. Which element does it actually refer to?

该短语 input$d3io 具有以下组件:

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

2) I have trouble understanding the custom binding part:

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");
  }
});

此代码使用名为 findrenderErrorrenderValue 的三个函数扩展了 d3OutputBinding 的行为。 Shiny.OutputBinding 需要这三个函数。

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

请注意,extend() 是 jQuery javascript 库的一个函数,在此上下文中的 $ 是 jQuery 对象的别名。

Shiny.outputBindings.register(d3OutputBinding);

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

干杯,尼克

关于javascript - 将 javascript (d3.js) 绑定(bind)到 shiny,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26650561/

相关文章:

javascript - 如何使行内 block 元素跨越文本行的其余部分?

r - 在R中如何合并列表

javascript - d3 : How to append nested elements on enter()? 我的元素被附加,但后续的选择看不到它们

r - 从文本中提取数据的最有效方法

Rshinyjs禁用函数在从另一个模块获取输入的模块中不起作用

javascript - 使用 D3 解析我的 CSV

javascript - react +D3 : Data over Y AXIS in scatter plot not appear correctly

javascript - 如何记录图层要素上请求的坐标

javascript - 在AngularJS中的指令中使用服务函数

javascript - 如何在 Nodejs 中模拟 "window"对象?