昨天 I asked 如何将带有自包含数据的d3js javacript文件放入Shiny中以绘制强制网络图。现在我正在寻找下一步:server.R将读取JSON数据文件以在图中显示。我一直在尝试调整使用messageHandlers的this example 来将数据传递到d3JS。这超出了我的专业知识,所以我正在寻求一些帮助。我很确定它在messageHandler中出现问题。
我很乐意发布完整的工作示例,因为这将使我对R,Shiny和d3JS集成有一个新的理解。 PS:是的,我看过networkD3和其他工具。我的d3JS图表比这里的简单示例复杂得多。 :)接下来的步骤还将包括使图表在Shiny中选择输入有反应,但我首先需要解决这个问题。 非常感谢! 添
ui.R - 按下按钮,接收图表!
shinyUI(fluidPage(
titlePanel("Shiny Binding to d3JS"),
sidebarLayout(
sidebarPanel(
tags$head(tags$link(rel = "stylesheet", type = "text/css", href = "twoNodes.css")),
actionButton("var_run",label="Create Graph!")
),
mainPanel(
h3("D3JS FN OUTPUT:"),
# load D3JS library
tags$script(src="d3.min.js"),
# load javascript
tags$script(src="twoNodes.js"),
# create div
tags$div(id="div_graph")
)
)
))
server.R - 当前读入两个节点及其链接。 IRL它会查询数据存储。
library(shiny)
library(rjson)
# Read JSON from the file
json_data <- fromJSON(file="twoNodes.JSON")
shinyServer(
function(input, output, session) {
# exception handler for when action button is clicked
# session$sendCustomMessage is where things start to fall apart
observe({
if (input$var_run == 0){
return()
}
session$sendCustomMessage(type="jsondata",json_data)
})
}
)
twoNodes.JSON - 数据
{
"nodes":[
{"id":0,"name":"Observations","group":"1"},
{"id":1,"name":"DataSet","group":"2"}
],
"edges":[
{"source":0,"target":1,"value":""}
]
}
twoNodes.css - 样式表
#nodegroup1{
fill:#000000;
fon-family: Serif, Georgia;
font-size: 14px;
font-weight: bold;
}
.nodetext{
font-size:8;
color: red;
}
.edgelabel{
font-size:12px;
fill:darkblue;
}
.edges{
stroke: #ccc;
stroke-width: 2;
}
twoNodes.js - 我试图利用的d3JS魔法
Shiny.addCustomMessageHandler("jsondata",
function(message){
var dataset = [message];
d3.select("#tempID").remove()
// lines from original d3JS follow
//Width and height for SVG area
var w = 300;
var h = 200;
// changed from body to #div_graph. Added tempID
var svg = d3.select("#div_graph").append("svg")
.attr("id","tempID")
.attr("width", w)
.attr("height", h);
svg.append("text")
.text("Two Nodes in a Force Network")
.attr("x",10)
.attr("y",15);
// Data source - Now comes in with message handler
// d3.json("/d3/CubeStructure/twoNodes.JSON", function(dataset) {
var force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.gravity(.05)
.charge(-180)
.linkDistance(100)
.size([w, h])
.start();
var drag = force.drag()
.on("dragstart", dragstart);
var edges = svg.selectAll("line")
.data(dataset.edges)
.enter()
.append("line")
.attr("id",function(d,i){return 'edge'+i})
.attr("class", "edges")
.attr("marker-end", "url(#end)");
var nodes = svg.selectAll("g.node")
.data(dataset.nodes)
.enter()
.append("g")
.attr("class", "node")
.on("dblclick", dblclick)
.call(drag);
nodes.append("circle")
.attr("r", 10)
.style("stroke", "black")
// Mousover Node - highlight node by fading the node colour during mouseover
.on('mouseover', function(d){
var nodeSelection = d3.select(this).style({opacity:'0.5'});
})
//Mouseout Node - bring node back to full colour
.on('mouseout', function(d){
var nodeSelection= d3.select(this).style({opacity:'1.0',})
})
// Node label
nodes.append("text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".35em")
.attr("id", function(d,i){return 'nodegroup1'}) // all get the same style
.text(function(d) { return d.name }); // Just the name
// Paths along which to apply the edge label
var edgepaths = svg.selectAll(".edgepath")
.data(dataset.edges)
.enter()
.append('path')
.attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
'class':'edgepath',
'fill-opacity':0,
'stroke-opacity':0,
'fill':'blue',
'stroke':'red',
'id':function(d,i) {return 'edgepath'+i}})
.style("pointer-events", "none");
// dx : the starting distance of the label from the source node
var edgelabels = svg.selectAll(".edgelabel")
.data(dataset.edges)
.enter()
.append('text')
.style("pointer-events", "none")
.attr({'class':'edgelabel',
'id':function(d,i){return 'edgelabel'+i},
'dx':40,
'dy':0
}) ;
force.on("tick", function() {
edges.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
nodes.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
edgepaths.attr('d', function(d) { var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y;
//console.log(d)
return path});
// positioning of the label along the edge
edgelabels.attr('transform',function(d,i){
if (d.target.x<d.source.x){
bbox = this.getBBox();
rx = bbox.x+bbox.width/2;
ry = bbox.y+bbox.height/2;
return 'rotate(180 '+rx+' '+ry+')';
}
else {
return 'rotate(0)';
}
});
});
// }); // not needed due to msg handler End of reading in JSON from file
// Double click to 'unfix' the node and have forces start to act on it again.
function dblclick(d) {
d3.select(this).classed("fixed", d.fixed = false);
}
// Set the "fixed" property of the dragged node to TRUE when a dragstart event is initiated,
// - removes "forces" from acting on that node and changing its position.
function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
}); // end of new function
答案 0 :(得分:1)
你很亲密。它只需稍加修改即可使用; twoNodes.js中的第3行应为
var dataset = message;