从 JSON 字符串而不是 JSON 文件渲染 D3 图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17622936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 19:57:12  来源:igfitidea点击:

Render D3 graph from a string of JSON instead of a JSON file

jsond3.js

提问by Quincy Larson

I am trying to render the following Dendrogram from my Rails app: http://bl.ocks.org/mbostock/4063570

我正在尝试从我的 Rails 应用程序呈现以下树状图:http: //bl.ocks.org/mbostock/4063570

I have a model with many attributes, but I would like to manually nest those attributes and simply use string interpolation to build up my own JSON string, then pass that to d3 directly.

我有一个具有许多属性的模型,但我想手动嵌套这些属性并简单地使用字符串插值来构建我自己的 JSON 字符串,然后将其直接传递给 d3。

Here is my code:

这是我的代码:

    <%= 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 %>

Here is my (unminified) JSON string:

这是我的(未缩小的)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"
                }
            }
        }
    }
}';

Things I've tried:

我尝试过的事情:

  1. minifying the JSON so it's inputted as just one line (no effect)

  2. running JSON.parse(mystring) on the string

  3. looking through the D3 documentation and and googling for a way to modify the following function to accept a string instead of a file path:

    d3.json("/assets/flare.json", function(root) {
            var nodes = cluster.nodes(root),
            links = cluster.links(nodes);
    
  1. 缩小 JSON,使其仅作为一行输入(无效)

  2. 在字符串上运行 JSON.parse(mystring)

  3. 查看 D3 文档并在谷歌上搜索修改以下函数以接受字符串而不是文件路径的方法:

    d3.json("/assets/flare.json", function(root) {
            var nodes = cluster.nodes(root),
            links = cluster.links(nodes);
    

回答by knolleary

First, lets look at what d3.jsondoes.

首先,让我们看看有什么d3.json作用。

d3.json("/assets/flare.json", function(root) {
    // code that uses the object 'root'
});

This loads the file /assets/flare.jsonfrom the server, interprets the contents as JSON and passes the resulting object as the rootargument to the anonymous function.

/assets/flare.json将从服务器加载文件,将内容解释为 JSON,并将结果对象作为root参数传递给匿名函数。

Where you already have a JSON object, you don't need to use the d3.jsonfunction - you can just use the object directly.

如果您已经有一个 JSON 对象,则不需要使用该d3.json函数 - 您可以直接使用该对象。

var root = {
   "name": "flare",
   "children": [
     ...
   ]
};
// code that uses the object 'root'

If the object is represented as a string, then you can use JSON.parseto get the object:

如果对象表示为字符串,则可以使用JSON.parse来获取对象:

var myString = '{"name": "flare","children": [ ... ] }';
var root = JSON.parse(mystring);
// code that uses the object 'root'

Second, lets look at what d3.layout.clusterexpects of your data. As per the docs:

其次,让我们看看d3.layout.cluster您对数据的期望。根据文档

... the default children accessor assumes each input data is an object with a children array ...

...默认子访问器假定每个输入数据是一个带有子数组的对象...

In other words, you data needs to be of the form:

换句话说,您的数据需要采用以下形式:

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"
                }
            ]
        }
    ]
}

回答by dehumanizer

d3.json actually takes URL as an argument, so instead of giving it the path to the file, I would suggest to delegate data management to the controller (especially, if in future you would need to load it from DB), so to simplify things:

d3.json 实际上将 URL 作为参数,所以我建议将数据管理委托给控制器(特别是,如果将来需要从 DB 加载它),而不是给它文件的路径,以便简化事物:

  1. Create a method in your controller, which would actually open the file and return its content:
  1. 在您的控制器中创建一个方法,它实际上会打开文件并返回其内容:
class YourFlareController < ApplicationController
    def load
        @data = File.read("app/assets/json/flare.json")
        render :json => @data
    end
end
class YourFlareController < ApplicationController
    def load
        @data = File.read("app/assets/json/flare.json")
        render :json => @data
    end
end
  1. Make sure you have a route in your routes.rb
  1. 确保你的 routes.rb 中有一条路线

get "yourflare/load"

得到“你的火炬/负载”

  1. And now in your javascript you can simply call
  1. 现在在你的javascript中你可以简单地调用

d3.json("http://host/yourflare/load", function(root) {

d3.json("http://host/yourflare/load", function(root) {