2012-09-18 26 views
11

Tôi đã tạo bố cục lực sử dụng d3 và nó hoạt động tốt. dữ liệu ban đầu của tôi được nạp từ một tập tin json và biểu đồ được vẽ bằng kỹ thuật tương tự như this d3.js example:Cập nhật các nút hiện có trong Bố cục Lực lượng d3

enter image description here

Bây giờ bảng xếp hạng là trên màn hình tôi cần phải bổ sung, cập nhật và loại bỏ các nút trên bay từ dữ liệu tôi nhận được qua một ổ cắm web. Tôi có thêm và loại bỏ các phương thức làm việc, nhưng tôi không thể tìm được cách chính xác để cập nhật các thuộc tính của nút hiện có.

Từ việc đọc tôi đã thực hiện, tôi thu thập kỹ thuật chính xác là thay đổi nguồn dữ liệu, sau đó cập nhật biểu đồ bằng cách sử dụng phương thức enter().

Để cập nhật một nút Tôi đang làm như sau:

function updateNode(id, word, size, trend, parent_id){  
    var updateNode = nodes.filter(function(d, i) { return d.id == id ? this : null; }); 
    if(updateNode[0]){ 
    updateNode.size = Number(size); 
    updateNode.trend = trend; 
    nodes[updateNode.index] = updateNode;  
    update(); 
    } 
} 

Chức năng cập nhật sau đó cập nhật các nút với:

function update(){ 
    node = vis.selectAll('.node') 
    .data(nodes, function(d) { 
    return d.id; 
    }) 

    createNewNodes(node.enter()); 
    node.exit().remove(); 
    force.start(); 
} 

function createNewNodes(selection){  
    var slct = selection.append('g') 
    .attr('class', 'node') 
    .call(force.drag); 

    slct.append('circle') 
    .transition() 
    .duration(500) 
    .attr('r', function(d) { 
     if(d.size){ 
     return Math.sqrt(sizeScale(d.size)*40); 
     } 
    }) 
} 

Tôi dùng phương pháp quyền này? Khi tôi thử mã này, nút mà tôi nhận được là datum khi cố gắng thiết lập thuộc tính radius trên vòng tròn là nút cuối cùng trong mảng nodes. I E. cái có chứa dữ liệu nút phân cấp thay vì một đối tượng nút đơn.

Bất kỳ con trỏ sẽ được đánh giá rất nhiều, tôi đã dành quá nhiều thời gian về vấn đề này :)

+0

Tôi có cùng một vấn đề, mặc dù trong bối cảnh đơn giản hơn nhiều. Bạn đã tìm thấy một giải pháp? –

+0

có thể đặt mã của bạn vào trình chỉnh sửa trực tuyến, ví dụ: http://phrogz.net/JS/d3-playground/#BlankDefault – ppoliani

Trả lời

7

Có nhiều điểm mà bạn cần. Những gì tôi nhận được từ câu hỏi của bạn là: 'làm thế nào để tôi sử dụng mô hình tái sử dụng'

Câu trả lời đơn giản cho câu hỏi này, sẽ để cho bạn biết để đọc hướng dẫn tuyệt vời này từ Mike Bostock: towards reusable charts

Nếu bạn muốn để có thêm thông tin, lựa chọn các tài liệu này có thể là thú vị:

Bây giờ, đây là một dự thảo của việc triển khai tôi sẽ làm cho vấn đề cụ thể của bạn:

function ForceGraph(selector,data) { 
    // This is the class that will create a graph 

    var _data = data 
    // Local variable representing the forceGraph data 

    svg = d3.select(selector) 
     .append('svg') 
    // Create the initial svg element and the utilities you will need. 
    // These are the actions that won't be necessary on update. 
    // For example creating the axis objects, your variables, or the svg container 

    this.data = function(value) { 
     if(!arguments.length) { 
     // accessor 
     return _data; 
     } 
     _data = value; 
     return this; 
     // setter, returns the forceGraph object 
    } 

    this.draw = function() { 
     // draw the force graph using data 

     // the method here is to use selections in order to do: 
     // selection.enter().attr(...) // insert new data 
     // selection.exit().attr(...) // remove data that is not used anymore 
     // selection.attr(...) // 

    } 
} 

var selector = "#graphId"; 
var data = {nodes: [...],links: [...]}; 
myGraph = new ForceGraph(selector,data); 
// Create the graph object 
// Having myGraph in the global scope makes it easier to call it from a json function or anywhere in the code (even other js files). 
myGraph.draw(); 
// Draw the graph for the first time 

// wait for something or for x seconds 

var newData = {nodes: [...],links: [...]}; 
// Get a new data object via json, user input or whatever 
myGraph.data(newData); 
// Set the graph data to be `newData` 
myGraph.draw(); 
// redraw the graph with `newData` 

Như bạn có thể thấy, mục tiêu không phải là để có một chức năng để thêm một nút mới. Mục tiêu là vẽ lại toàn bộ đồ thị lực theo hướng chỉ bằng cách cập nhật hoặc loại bỏ các nút hiện có và thêm các nút mới. Bằng cách này, mã vẽ chỉ được viết một lần, sau đó chỉ thay đổi dữ liệu.

Để đọc thêm, câu hỏi này là mỏ vàng của tôi khi tôi lần đầu tiên giải quyết vấn đề này: Updating links on a force directed graph from dynamic json data

Các vấn đề liên quan