Yesterday I asked how to bring a d3js javacript file with offline data to Shiny in order to draw a power network graph. Now I'm looking for the next step: server.R will read the JSON data file for display on the chart. I tried to adapt this example , which uses messageHandlers to transfer data to d3JS. This is beyond my experience, so I'm looking for some help. I am pretty sure this is in messageHandler where everything goes wrong.
I will gladly publish a full working example, because it will lead me to a new level of understanding of the integration of R, Shiny and d3JS. PS: Yes, I looked at networkD3 and other tools. My d3JS diagrams are much more complicated than a simple example. :) The following steps also include creating a graph that responds to input choices in Shiny, but I need this problem first of all. Thank you very much! Tim
ui.R - click the button, get the schedule!
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:"),
tags$script(src="d3.min.js"),
tags$script(src="twoNodes.js"),
tags$div(id="div_graph")
)
)
))
server.R - Currently read in two nodes and their link. IRL will request a data warehouse.
library(shiny)
library(rjson)
json_data <- fromJSON(file="twoNodes.JSON")
shinyServer(
function(input, output, session) {
observe({
if (input$var_run == 0){
return()
}
session$sendCustomMessage(type="jsondata",json_data)
})
}
)
twoNodes.JSON - data
{
"nodes":[
{"id":0,"name":"Observations","group":"1"},
{"id":1,"name":"DataSet","group":"2"}
],
"edges":[
{"source":0,"target":1,"value":""}
]
}
twoNodes.css - style sheet
#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 is the d3JS magic I'm trying to use
Shiny.addCustomMessageHandler("jsondata",
function(message){
var dataset = [message];
d3.select("#tempID").remove()
var w = 300;
var h = 200;
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);
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")
.on('mouseover', function(d){
var nodeSelection = d3.select(this).style({opacity:'0.5'});
})
.on('mouseout', function(d){
var nodeSelection= d3.select(this).style({opacity:'1.0',})
})
nodes.append("text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".35em")
.attr("id", function(d,i){return 'nodegroup1'})
.text(function(d) { return d.name });
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");
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;
return path});
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)';
}
});
});
function dblclick(d) {
d3.select(this).classed("fixed", d.fixed = false);
}
function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
});