闪亮的自定义输出不渲染 [英] Shiny Custom Output not Rendering

查看:129
本文介绍了闪亮的自定义输出不渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将来自D3.js的网络可视化绑定到Shiny中的自定义输出。由于某些原因,似乎我的渲染函数没有被调用。这是我的代码:

I'm trying to bind a network visualization from D3.js to a custom output in Shiny. For some reason, it seems like my rendering functions are not being called. Here is my code:

rbindings.js

rbindings.js

var forceNetworkOB = new Shiny.OutputBinding();

forceNetworkOB.find = function(scope) {
  return $(scope).find("svg.rio-force-network");
};

forceNetworkOB.renderValue = function(el, graph) {

  alert('rendering')

  //actual rendering code here...

};

Shiny.outputBindings.register(forceNetworkOB, "jumpy.forceNetworkOB");

CustomIO.R

CustomIO.R

renderForceNetwork <- function(expr, env=parent.frame(), quoted=FALSE) {

  func <- exprToFunction(expr, env, quoted)

  function() {

    # Never called
    browser()

    graph <- func()

    list(nodes = graph$nodes,
         links = graph$edges
    )
  }
}

forceNetwork <- function(id, width = '400px', height = '400px') {

  tag('svg', list(id = id, class = 'rio-force-network', width = width, height = height))

}

ui.R

library(shiny)
source('customIO.R')

shinyUI(fluidPage(

  tags$script(src = 'js/d3.min.js'),
  tags$script(src = 'js/rbindings.js'),

  titlePanel('Network Visualization'),

  tabsetPanel(
    tabPanel('D3.js Force Layout',
      forceNetwork('vis.force', width = '800px', height = '800px'),
    )
  )

))

和server.R

library(shiny)

source('cytoscape.R')
source('customIO.R')

shinyServer(function(session, input, output) {


  # Load the network
  network <- networkFromCytoscape('network.cyjs')

  output$vis.force <- renderForceNetwork({

    # Never called
    print('rendering')
    browser()

    list(
      nodes = data.frame(name = network$nodes.data$Label_for_display, group = rep(1, nrow(network$nodes.data))),
      edges = data.frame(from = network$edges[,1], to = network$edges[,2])
    )

  })

})

正如你从评论中看到的,浏览器()在我的R渲染函数中的行不会被调用,以及js渲染函数中的alert()。有了一些js调试,我可以看到我的自定义绑定正确地给svg元素渲染以及其id。这可能是简单的,但我不能弄清楚。

As you can see from the comments, the browser() lines in my R rendering functions are never called, as well as the alert() in the js rendering function. With some js debugging I can see that my custom binding is correctly giving the svg element to render to as well as its id. This might be something simple but I cannot figure it out.

推荐答案

当Shiny初始化时,它调用 initShiny()然后调用 bindOutputs
现在,这里是 bindOutputs 函数看起来像:

When Shiny initializes, it calls initShiny(), which then calls bindOutputs. Now, here is what the bindOutputs function looks like:

function bindOutputs(scope) {

  if (scope === undefined)
    scope = document;

  scope = $(scope);

  var bindings = outputBindings.getBindings();

  for (var i = 0; i < bindings.length; i++) {
    var binding = bindings[i].binding;
    var matches = binding.find(scope) || [];
    for (var j = 0; j < matches.length; j++) {
      var el = matches[j];
      var id = binding.getId(el);

      // Check if ID is falsy
      if (!id)
        continue;

      var bindingAdapter = new OutputBindingAdapter(el, binding);
      shinyapp.bindOutput(id, bindingAdapter);
      $(el).data('shiny-output-binding', bindingAdapter);
      $(el).addClass('shiny-bound-output'); // <- oops!
    }
  }

  // Send later in case DOM layout isn't final yet.
  setTimeout(sendImageSize, 0);
  setTimeout(sendOutputHiddenState, 0);
}

标记为的行是什么原因导致所有的问题。
这真的不是Shiny 本身的错误:这行代码依靠 jQuery 添加一个类到 el ,它是使用 forceNetwork() svg c $ c>函数。

The line I marked with <- oops is what causes all the problem. This really isn't a bug of Shiny per se: this line of code relies on jQuery to add a class to el, which is the svg DOM element that you've created with forceNetwork() function.

shiny-bound-output / em>绑定到工作。

The class shiny-bound-output is important for the actual binding to work.

问题是 $。addClass < svg>
为了方便参考,请参阅这篇文章这个问题在stackoverflow

因此,因此,您的< svg> 元素缺少必需的 -bound-output 类,这将使您的自定义 OutputBinding 正确运行。

So, as a result, your <svg> element lacks the required shiny-bound-output class that would make your custom OutputBinding to function correctly.

不要使用< svg> 作为您的输出的容器。请改用< div>
这意味着,您应该将 forceNetwork 函数更改为:

Don't use <svg> as the container of your output. Use a <div> instead. It means, you should change your forceNetwork function to:

forceNetwork <- function(id, width = '400px', height = '400px') {    
  tag('div', list(id = id, class = 'rio-force-network', width = width, height = height))
}

$ c>< svg> 使用 d3.select(...)。append('svg')

You can easily append a <svg> using d3.select(...).append('svg') and set the width and height there.

(请记住修改中的 find()函数 rbindings.js 以及)。

(Remember to modify your find() function in rbindings.js as well).

如果您以某种方式向您的JavaScript代码添加 d3.select(...)。append('svg'),请记住中的< div> 实际d3绘图。否则每次 renderForceNetwork 被调用时,它将为您的添加一个新的< svg> >< div> 容器。

If you somehow add d3.select(...).append('svg') to your javascript code, remember to clear() the <div> container in the output binding's renderValue() function before the actual d3 drawing. Otherwise every time renderForceNetwork is called, it will add a new <svg> element to your <div> container.

这篇关于闪亮的自定义输出不渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆