2013-07-12 13 views
10

Tôi cố gắng để làm cho Dendrogram sau từ ứng dụng Rails của tôi: http://bl.ocks.org/mbostock/4063570Render D3 đồ thị từ một chuỗi JSON thay vì một tập tin JSON

Tôi có một mô hình với nhiều thuộc tính, nhưng tôi muốn tự tổ các thuộc tính đó và chỉ cần sử dụng phép nội suy chuỗi để xây dựng chuỗi JSON của riêng tôi, sau đó chuyển trực tiếp chuỗi đó sang d3.

Đây là mã của tôi:

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

Sau đây là tôi (unminified) chuỗi 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" 
       } 
      } 
     } 
    } 
}'; 

Những điều tôi đã cố gắng:

1) rút gọn JSON vì vậy nó đầu vào chỉ là một dòng (không có hiệu lực)

2) chạy JSON.parse (mystring) trên chuỗi

3) xem qua tài liệu D3 và googling để biết cách sửa đổi hàm sau để chấp nhận chuỗi thay vì đường dẫn tệp: d3.json ("/ assets/flare.json", hàm (root) { var nodes = cluster.nodes (root), links = cluster.links (nút);

Trả lời

23

Trước tiên, hãy xem những gì d3.json thực hiện.

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

này tải file /assets/flare.json từ máy chủ, giải thích các nội dung như JSON và vượt qua các đối tượng kết quả như root tranh luận với chức năng ẩn danh.

Nơi bạn đã có đối tượng JSON, bạn không cần sử dụng chức năng d3.json - bạn chỉ có thể sử dụng trực tiếp đối tượng.

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

Nếu đối tượng được biểu diễn dưới dạng một chuỗi, sau đó bạn có thể sử dụng JSON.parse để có được những đối tượng:

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

Thứ hai, cho phép nhìn vào những gì d3.layout.cluster hy vọng dữ liệu của bạn. Theo the docs:

... những đứa trẻ mặc định accessor giả mỗi dữ liệu đầu vào là một đối tượng với một mảng trẻ em ...

Nói cách khác, bạn có dữ liệu cần phải có dạng:

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

knolleary, cảm ơn bạn cho explana sự. Điều này là hữu ích, nhưng những gì tôi đang tìm kiếm cụ thể là: Làm thế nào để thay đổi d3.json ("/ assets/flare.json", hàm (root) {line để cho phép một chuỗi cục bộ? D3.json của cú pháp là: d3.json (url [, gọi lại]) Tôi muốn chạy hàm ẩn danh trên chuỗi của tôi, thay vì URL –

+4

Michael, bạn thay đổi dòng d3.json (..) bằng cách loại bỏ nó ... nếu bạn đã có chuỗi, bạn không cần sử dụng hàm để tải nội dung từ url, đó là tất cả những gì d3.json thực hiện. Hàm ẩn danh hiện được chỉ định trong d3.json (..) gọi đơn giản có thể được gọi một cách rõ ràng với chuỗi bạn có Đây là những gì tôi đã cố gắng để mô tả trong nửa đầu của câu trả lời của tôi – knolleary

+0

làm thế nào tôi có thể tải một tập tin json thay vì nó luôn luôn đưa ra lỗi cho tôi –

3

d3.json thực sự lấy URL làm đối số, vì vậy thay vì cho nó đường dẫn đến tệp, tôi sẽ đề nghị ủy quyền quản lý dữ liệu cho bộ điều khiển (đặc biệt, nếu trong tương lai bạn cần tải nó từ DB), để đơn giản hóa mọi thứ:

  1. Tạo một phương pháp trong điều khiển của bạn, mà thực sự sẽ mở file và gửi lại nội dung của nó:
class YourFlareController < ApplicationController 
    def load 
     @data = File.read("app/assets/json/flare.json") 
     render :json => @data 
    end 
end 
  1. Hãy chắc chắn rằng bạn có một tuyến đường trong tuyến đường của bạn rb

get "yourflare/tải"

  1. Và bây giờ trong javascript của bạn, bạn có thể chỉ cần gọi

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