我正在尝试从我的Rails应用程序渲染以下树形图: http://bl.ocks.org/mbostock/4063570
我有一个具有许多属性的模型,但我想手动嵌套这些属性,只需使用字符串插值来构建我自己的JSON字符串,然后直接将其传递给d3。
这是我的代码:
<%= javascript_tag do %>
var width = 960,
height = 2200;
var cluster = d3.layout.cluster()
.size([height, width - 160]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(40,0)");
**d3.json("/assets/flare.json", function(root) {**
var nodes = cluster.nodes(root),
links = cluster.links(nodes);
var link = svg.selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "link")
.attr("d", diagonal);
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("dx", function(d) { return d.children ? -8 : 8; })
.attr("dy", 3)
.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.name; });
});
d3.select(self.frameElement).style("height", height + "px");
<% end %>
这是我的(未经通知的)JSON字符串:
var mystring = '{
"name": "Product",
"properties": {
"id": {
"type": "number",
"description": "Product identifier",
"required": true
},
"name": {
"type": "string",
"description": "Name of the product",
"required": true
},
"price": {
"type": "number",
"minimum": 0,
"required": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"stock": {
"type": "object",
"properties": {
"warehouse": {
"type": "number"
},
"retail": {
"type": "number"
}
}
}
}
}';
我尝试过的事情:
缩小JSON,使其只输入一行(无效)
在字符串
查看D3文档,然后使用Google搜索方法修改以下函数以接受字符串而不是文件路径:
d3.json("/assets/flare.json", function(root) {
var nodes = cluster.nodes(root),
links = cluster.links(nodes);
答案 0 :(得分:29)
首先,让我们看看d3.json
做了什么。
d3.json("/assets/flare.json", function(root) {
// code that uses the object 'root'
});
从服务器加载文件/assets/flare.json
,将内容解释为JSON,并将生成的对象作为root
参数传递给匿名函数。
如果您已经拥有JSON对象,则无需使用d3.json
函数 - 您可以直接使用该对象。
var root = {
"name": "flare",
"children": [
...
]
};
// code that uses the object 'root'
如果对象表示为字符串,则可以使用JSON.parse
来获取对象:
var myString = '{"name": "flare","children": [ ... ] }';
var root = JSON.parse(mystring);
// code that uses the object 'root'
其次,让我们看一下d3.layout.cluster
对数据的期望。根据{{3}}:
...默认的子访问器假定每个输入数据都是带有子数组的对象...
换句话说,您的数据必须采用以下形式:
var mystring = '{
"name": "Product",
"children": [
{
"name": "id",
"type": "number",
"description": "Product identifier",
"required": true
},
...
{
"name": "stock",
"type": "object",
"children": [
{
"name: "warehouse",
"type": "number"
},
{
"name": "retail",
"type": "number"
}
]
}
]
}
答案 1 :(得分:2)
d3.json实际上将URL作为参数,因此我建议将数据管理委托给控制器(特别是如果将来需要从DB加载),而不是给它提供文件的路径,所以简化一下:
class YourFlareController < ApplicationController def load @data = File.read("app/assets/json/flare.json") render :json => @data end end
获取“yourflare / load”
d3.json("http://host/yourflare/load", function(root) {