2013-02-08 34 views
6

Tôi đã ở đó trong một vài tuần và dường như không thể tìm ra cách vẽ biểu đồ dưới đây bằng nhiều đường dẫn. Focus+Context via Brushing chartGặp sự cố khi vẽ d3.js Tiêu điểm + Ngữ cảnh qua biểu đồ Đánh dấu với nhiều đường dẫn

Tôi đã cố tạo một jsfiddle nhưng không thể tái tạo màn hình mà tôi nhận được. Tại thời điểm này những gì tôi có là tương tự như biểu đồ ban đầu chỉ với một con đường thay vì khu vực và các công trình đánh răng. Về cơ bản, cố gắng kết hợp biểu đồ Focus và Biểu đồ đường dây nhiều dòng Multiseries chart.

Tuy nhiên, khi tôi cố thêm một đường dẫn khác thì không có gì hoạt động. Vui lòng đề xuất bất kỳ ý tưởng hoặc thay đổi nào mà tôi cần để làm cho nó hoạt động. Ngoài ra còn có bất kỳ biểu đồ tương tự khác (hoặc biểu đồ exaples) mà tôi có thể nhìn vào. Dữ liệu có thể được sắp xếp lại theo bất kỳ cách thức hoặc hình thức nào để làm việc này.

Jsfiddle

<div id='dashboardChart'> 
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
id="svg"> 
</div> 

path { 
fill:none; 
stroke:white; 
stroke-width:2px; 
} 
.axis path, .axis line { 
    fill: none; 
    stroke: #CCC; 
    shape-rendering: crispEdges; 
} 
.brush .extent { 
    stroke: #fff; 
    fill-opacity: .125; 
    shape-rendering: crispEdges; 
} 
.path_green { 
    stroke:green; 
} 
.path_red { 
    stroke:red; 
} 
.path_yellow { 
    stroke:yellow; 
} 

function drawChart() { 
    var margin = { 
     top: 5, 
     right: 10, 
     bottom: 100, 
     left: 50 
    }, 
    margin2 = { 
     top: 200, 
     right: 10, 
     bottom: 20, 
     left: 50 
    }, 
    width = 1075 - margin.left - margin.right, 
     height = 280 - margin.top - margin.bottom, 
     height2 = 280 - margin2.top - margin2.bottom; 

    var parseDate = d3.time.format("%Y-%m-%d").parse; 

    var x = d3.time.scale().range([0, width]), 
     x2 = d3.time.scale().range([0, width]), 
     y = d3.scale.linear().range([height, 0]), 
     y2 = d3.scale.linear().range([height2, 0]); 

    var xAxis = d3.svg.axis().scale(x).orient("bottom"), 
     xAxis2 = d3.svg.axis().scale(x2).orient("bottom"), 
     yAxis = d3.svg.axis().scale(y).orient("left"); 

    var brush = d3.svg.brush() 
     .x(x2) 
     .on("brush", brush); 

    var area = d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
     return x(d.date); 
    }) 
     .y0(height) 
     .y1(function (d) { 
     return y(d.red); 
    }); 

    var area2 = d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
     return x2(d.date); 
    }) 
     .y0(height2) 
     .y1(function (d) { 
     return y2(d.red); 
    }); 

    var svg = d3.select("#dashboardChart #svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom); 

    svg.append("defs").append("clipPath") 
     .attr("id", "clip") 
     .append("rect") 
     .attr("width", width) 
     .attr("height", height); 

    var focus = svg.append("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    var context = svg.append("g") 
     .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); 

    var data = [{ 
     "date": "2013-02-08T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 1 
    }, { 
     "date": "2013-02-07T05:00:00.000Z", 
     "data": null, 
     "red": 485, 
     "yellow": 0, 
     "green": 491 
    }, { 
     "date": "2013-02-06T05:00:00.000Z", 
     "data": null, 
     "red": 2884, 
     "yellow": 0, 
     "green": 2881 
    }, { 
     "date": "2013-02-05T05:00:00.000Z", 
     "data": null, 
     "red": 3191, 
     "yellow": 0, 
     "green": 3188 
    }, { 
     "date": "2013-02-04T05:00:00.000Z", 
     "data": null, 
     "red": 180, 
     "yellow": 0, 
     "green": 184 
    }, { 
     "date": "2013-02-03T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-02-02T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-02-01T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-31T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-30T05:00:00.000Z", 
     "data": null, 
     "red": 1, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-29T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 2 
    }, { 
     "date": "2013-01-28T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-27T05:00:00.000Z", 
     "data": null, 
     "red": 1, 
     "yellow": 1, 
     "green": 1 
    }, { 
     "date": "2013-01-26T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 1 
    }, { 
     "date": "2013-01-25T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-24T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-23T05:00:00.000Z", 
     "data": null, 
     "red": 49, 
     "yellow": 0, 
     "green": 45 
    }, { 
     "date": "2013-01-22T05:00:00.000Z", 
     "data": null, 
     "red": 59, 
     "yellow": 0, 
     "green": 64 
    }, { 
     "date": "2013-01-21T05:00:00.000Z", 
     "data": null, 
     "red": 119, 
     "yellow": 1, 
     "green": 125 
    }, { 
     "date": "2013-01-20T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 1, 
     "green": 0 
    }, { 
     "date": "2013-01-19T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-18T05:00:00.000Z", 
     "data": null, 
     "red": 84, 
     "yellow": 0, 
     "green": 81 
    }, { 
     "date": "2013-01-17T05:00:00.000Z", 
     "data": null, 
     "red": 76, 
     "yellow": 1, 
     "green": 77 
    }, { 
     "date": "2013-01-16T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 1, 
     "green": 0 
    }, { 
     "date": "2013-01-15T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-14T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-13T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-12T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-11T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-10T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }]; 

    x.domain(d3.extent(data.map(function (d) { 
     return d.date; 
    }))); 
    y.domain([0, d3.max(data.map(function (d) { 
     return d.red; 
    }))]); 
    x2.domain(x.domain()); 
    y2.domain(y.domain()); 

    focus.append("path") 
     .datum(data) 
     .attr("clip-path", "url(#clip)") 
     .attr("d", area) 
     .attr("class", "path_red"); 

    focus.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    focus.append("g") 
     .attr("class", "y axis") 
     .call(yAxis); 

    context.append("path") 
     .datum(data) 
     .attr("d", area2) 
     .attr("class", "path_red"); 

    context.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height2 + ")") 
     .call(xAxis2); 

    context.append("g") 
     .attr("class", "x brush") 
     .call(brush) 
     .selectAll("rect") 
     .attr("y", -6) 
     .attr("height", height2 + 7); 

    function brush() { 
     x.domain(brush.empty() ? x2.domain() : brush.extent()); 
     focus.select("path").attr("d", area); 
     focus.select(".x.axis").call(xAxis); 
    } 
} 
drawChart(); 
+0

tôi đã có thể rút ra 3 khu vực để tái tạo 3 bộ dữ liệu một trên đầu trang của mỗi khác nhưng không thể "bàn chải" cả ba. Nó chỉ hoạt động với một khu vực. Có thể "chải" làm việc trên ba khu vực cùng một lúc? Làm thế nào điều này có thể được mã hóa? –

Trả lời

10

Theo nhận xét của bạn, bạn đã có thể vẽ ba lĩnh vực nhưng gặp khó khăn trong đánh răng họ. Tôi có một ví dụ làm việc tại đây: http://jsfiddle.net/BVzyq/1/ trong đó, tôi đã thêm ba phần tử <path> tương ứng với ba màu màu trong dữ liệu: ['red', 'yellow', 'green'].

tôi trừu tượng hiện các chức năng mà có thể mất trong một màu sắc và trả về giá trị thích hợp d:

var area = function (color) { 
    return d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
      return x(d.date); 
     }) 
     .y0(height) 
     .y1(function (d) { 
      return y(d[color]); 
     }); 
}; 

var area2 = function (color) { 
    return d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
      return x2(d.date); 
     }) 
     .y0(height2) 
     .y1(function (d) { 
      return y2(d[color]); 
     }); 
}; 

Họ có thể được trừu tượng hơn nữa, nhưng đây là những gần gũi nhất với các mã bạn đã viết. Các chức năng này được sử dụng trong khi tạo đường dẫn:

focus.selectAll('path') 
    .data(['red', 'yellow', 'green']) 
    .enter() 
    .append('path') 
    .attr('clip-path', 'url(#clip)') 
    .attr('d', function (col) { 
     return area(col)(data); 
    }) 
    .attr('class', function (col) { 
     return "path_" + col + " data"; 
    }); 

// ... 

context.selectAll('path') 
    .data(['red', 'yellow', 'green']) 
    .enter() 
    .append('path') 
    .attr('d', function (col) { 
     return area2(col)(data); 
    }) 
    .attr('class', function (col) { 
     return "path_" + col; 
    }); 

Các lớp CSS dường như đề xuất dạng tham gia dữ liệu này. Tôi cũng đã thêm một lớp khác data vào các đường dẫn tương ứng với các ô chuỗi thời gian. Điều này làm cho nó dễ dàng để phân biệt các <path> s này từ những ý nghĩa cho trục.

Cuối cùng, trong chức năng bàn chải, tính toán lại các thuộc tính d cho tất cả path.data yếu tố:

function brush() { 
    x.domain(brush.empty() ? x2.domain() : brush.extent()); 
    focus.selectAll("path.data").attr("d", function (col) { 
     return area(col)(data); 
    }); 
    focus.select(".x.axis").call(xAxis); 
} 

Lưu ý rằng tôi đã thay đổi một số giá trị trong data để làm cho tất cả ba màu nhìn thấy được.

+2

Tuyệt vời, bạn xứng đáng có một anh chàng huy chương. – Melki

2

Giải pháp tuyệt vời musically_ut, đối với những người khác gặp sự cố tương tự. Tôi đã có thể tải thêm csv, giống như ví dụ được tìm thấy trong liên kết này - Focus+Context via Brushing nhưng thực sự đã treo trên cách đánh dấu tất cả các dòng với nhau, mặc dù chúng đều được hiển thị chính xác trong khu vực và khu vực2.

Hóa ra, nhìn vào mã của bạn, tất cả những gì tôi phải làm là thay đổi focus.select thành focus.selectTất cả những gì bạn có. Cảm ơn!

Và đối với bất cứ ai làm việc với mã hướng dẫn ban đầu, bạn có thể thêm csv thay thế chỉ là bằng cách sao chép đoạn mã sau và trỏ đến csv mới của bạn:

d3.csv("sp501.csv", function(error, data) { 

     data.forEach(function(d) { 
     d.date = parseDate(d.date); 
     d.price = +d.price; 
     }); 

     x.domain(d3.extent(data.map(function(d) { return d.date; }))); 
     y.domain([0, d3.max(data.map(function(d) { return d.price; }))]); 
     x2.domain(x.domain()); 
     y2.domain(y.domain()); 

     focus.append("path") 
      .datum(data) 
      .attr("clip-path", "url(#clip)") 
      .attr("d", area) 
      .attr("class", "timeLine2"); 

     context.append("path") 
      .datum(data) 
      .attr("class", "timeLine2") 
      .attr("d", area2); 

     context.append("g") 
      .attr("class", "x axis2") 
      .attr("transform", "translate(0," + height2 + ")") 
      .call(xAxis2); 

     context.append("g") 
      .attr("class", "x brush") 
      .call(brush) 
     .selectAll("rect") 
      .attr("y", -6) 
      .attr("height", height2 + 7); 
    }); 
Các vấn đề liên quan