我可以为我的闪亮界面使用 index.html 和 ui.r 吗?

Can I use index.html and ui.r for my r shiny interface?

参考 this 关于如何在 HTML 中完全构建你的闪亮应用程序,我想知道是否有任何方法可以将这种方法与传统的 [=18] 结合使用=]方法。

原因:This 将 D3 与 R Shiny 一起使用的方法似乎需要将所有 D3 代码放入 index.html 文件中。但我还想要一些交互性(selectInputs、dateRangeInputs、多个选项卡等)。有什么建议吗?

我的理解是,使用 index.html 可以替代 ui.R,在需要使用 HTML 代码的 "cost" 处提供更多功能(相对于 "out-of-the-box" 闪亮的功能,如 selectInputs 等...这些实际上只是将一系列输入转换为 HTML 代码)。

要在 index.html 中找到等效函数,一个技巧是创建 ui.R,然后在浏览器中查看页面源代码。这将为您提供正确的 HTML 代码以在您闪亮的应用程序中实施。例如,选项卡可能如下所示:

<div class="container-fluid">
    <div class="tabbable tabs-above">
      <ul class="nav nav-tabs">
        <li class="active">
          <a href="#tab-5303-1" data-toggle="tab" data-value="Graphs">Graphs</a>
        </li>
        <li>
          <a href="#tab-5303-2" data-toggle="tab" data-value="Size Data">Size Data</a>
        </li>
        <li>
          <a href="#tab-5303-3" data-toggle="tab" data-value="Data Bins">Data Bins</a>
        </li>
      </ul>

...

<div class="tab-content">
        <div class="tab-pane active" data-value="Graphs" id="tab-5303-1">

...

    </div>
  </div>

一旦您弄清楚如何将 UI 参数转换为 HTML 代码,这就相当简单了。您提供的 link 很好地总结了如何连接到您的服务器文件。

您可以使用 tags 将自定义 HTML 添加到您的 ui.R

对于更复杂的输出,您可以在使用带有 ui.Rserver.R 的应用程序时构建自定义闪亮输出。 This page 有关于如何对任何代码执行此操作的信息。

这是一个使用您发布的 D3 示例中的 javascript 代码的示例。 该应用程序仅生成绘图,我添加了一个 selectInput ,您可以在其中 select 它绘制的数据以显示事物如何整合。所有 javascript 代码均来自 mbostock。 (可以查到here)。

我添加了闪亮的绑定部分并更改了几行以使其适应应用程序,我在更改上方进行了评论以便您可以跟踪它们。

ui.R

library(shiny)

shinyUI(
  fluidPage(singleton(tags$head(
    #adds the d3 library needed to draw the plot
    tags$script(src="http://d3js.org/d3.v3.min.js"),

    #the js script holding the code to make the custom output
    tags$script(src="HierarchicalEdgeBundling.js"),

    #the stylesheet, paste all that was between the <style> tags from your example in the graph_style.css file
    tags$link(rel = "stylesheet", type = "text/css", href = "graph_style.css")
  )),
    mainPanel(

      #this select input allows the user to choose json files in the www directory
      selectInput("data_files", "JSON files:" ,  as.matrix(list.files(path="www",pattern="json"))),

      #this div will hold the final graph
      div(id="graph", class="HierarchicalEdgeBundling")
    )        
  )
)

server.R

shinyServer(function(input, output, session) {

  #output to the graph div
  output$graph <- reactive({
    #get the selected file
    input$data_files
  })
})

HierarchicalEdgeBundling.js

//shiny output binding
var binding = new Shiny.OutputBinding();

binding.find = function(scope) {
        return $(scope).find(".HierarchicalEdgeBundling");
};



binding.renderValue = function(el, data) {
//empty the div so that it removes the graph when you change data
  $(el).empty()

if(data!=null){
  var diameter = 960,
      radius = diameter / 2,
      innerRadius = radius - 120;

  var cluster = d3.layout.cluster()
      .size([360, innerRadius])
      .sort(null)
      .value(function(d) { return d.size; });

  var bundle = d3.layout.bundle();

  var line = d3.svg.line.radial()
      .interpolate("bundle")
      .tension(.85)
      .radius(function(d) { return d.y; })
      .angle(function(d) { return d.x / 180 * Math.PI; });

  //select the div that has the same id as the el id 
  var svg = d3.select("#" + $(el).attr('id')).append("svg")
      .attr("width", diameter+300)
      .attr("height", diameter+300)
    .append("g")
      .attr("transform", "translate(" + radius + "," + radius + ")");

  var link = svg.append("g").selectAll(".link"),
      node = svg.append("g").selectAll(".node");

  //add the data from the user input
  d3.json(data, function(error, classes) {
    var nodes = cluster.nodes(packageHierarchy(classes)),
        links = packageImports(nodes);

    link = link
        .data(bundle(links))
      .enter().append("path")
        .each(function(d) { d.source = d[0], d.target = d[d.length - 1]; })
        .attr("class", "link")
        .attr("d", line);

    node = node
        .data(nodes.filter(function(n) { return !n.children; }))
      .enter().append("text")
        .attr("class", "node")
        .attr("dy", ".31em")
        .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); })
        .style("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
        .text(function(d) { return d.key; })
        .on("mouseover", mouseovered)
        .on("mouseout", mouseouted);
  });

  function mouseovered(d) {
    node
        .each(function(n) { n.target = n.source = false; });

    link
        .classed("link--target", function(l) { if (l.target === d) return l.source.source = true; })
        .classed("link--source", function(l) { if (l.source === d) return l.target.target = true; })
      .filter(function(l) { return l.target === d || l.source === d; })
        .each(function() { this.parentNode.appendChild(this); });

    node
        .classed("node--target", function(n) { return n.target; })
        .classed("node--source", function(n) { return n.source; });
  }

  function mouseouted(d) {
    link
        .classed("link--target", false)
        .classed("link--source", false);

    node
        .classed("node--target", false)
        .classed("node--source", false);
  }

  d3.select(self.frameElement).style("height", diameter + "px");

  // Lazily construct the package hierarchy from class names.
  function packageHierarchy(classes) {
    var map = {};

    function find(name, data) {
      var node = map[name], i;
      if (!node) {
        node = map[name] = data || {name: name, children: []};
        if (name.length) {
          node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
          node.parent.children.push(node);
          node.key = name.substring(i + 1);
        }
      }
      return node;
    }

    classes.forEach(function(d) {
      find(d.name, d);
    });

    return map[""];
  }

  // Return a list of imports for the given array of nodes.
  function packageImports(nodes) {
    var map = {},
        imports = [];

    // Compute a map from name to node.
    nodes.forEach(function(d) {
      map[d.name] = d;
    });

    // For each import, construct a link from the source to target node.
    nodes.forEach(function(d) {
      if (d.imports) d.imports.forEach(function(i) {
        imports.push({source: map[d.name], target: map[i]});
      });
    });

    return imports;
  }
}
};

//register the output binding
Shiny.outputBindings.register(binding, "HierarchicalEdgeBundling");

要使该应用程序正常运行,您需要在与 ui.Rserver.R 相同的目录中创建一个 www 文件夹,并将 HierarchicalEdgeBundling.js 文件放入其中, css 在 graph_style.css 文件中找到 here,并且 json 数据文件(例如 data1.jsondata2.json)。