1

tablib CSV を D3.js にフィードする Django View があります。ただし、exit() を使用する方法や場所に関係なく、何も返されないことがわかりました。そのため、古い不要な要素を削除することはできず、すべてが互いに重なり合うだけです。

何か案は?基本的な積み上げ棒グラフの例から、かなりハードにコードを作成しました。

<div id="id_d3_canvas" class="d3_canvas_space">
</div>
<div>
<form id="id_date_form">
    <input id="id_date_small" name="date1" type="text" value="03-01-2012">
    <input id="id_date_large" name="date2" type="text" value="{% now 'n-j-Y' %}">
    <select name="our_people" multiple>
        {% for person in object_list %}
        <option value="{{ person.name }}" selected>{{ person.name }}</option>
        {% endfor %}
    </select>
</form>
<button id="id_test_data_gather" class="btn btn-primary update_d3_csv">Update</button>
</div>

<script src="{{ STATIC_URL }}cms/js/d3.min.js"></script>
<script>
    var margin = {top: 20, right: 20, bottom: 30, left: 40},
        width = 900 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);

    var y = d3.scale.linear()
        .rangeRound([height, 0]);

    var color = d3.scale.ordinal()
        .range(["#98abc5", "#ff8c00"]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .tickFormat(d3.format(".2s"));

    var svg = d3.select(".d3_canvas_space").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var date_info = $("#id_date_form").serialize(),
        initial_csv_url = "{% url blahblah %}?" + date_info;


    function updateMultiData(multi_csv_url) { 
        d3.csv(multi_csv_url, function(error, data) {
            color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Name"; }));

            data.forEach(function(d) {
                var y0 = 0;
                d.tasks = color.domain().map(function(category) { return {category: category, y0: y0, y1: y0 += +d[category]};});
                d.total_tasks = d.tasks[d.tasks.length - 1].y1;
            });

            data.sort(function(a, b) { return b.total - a.total; });

            x.domain(data.map(function(d) { return d.Name; }));
            y.domain([0, d3.max(data, function(d) { return d.total_tasks; })]);

            svg.selectAll(".name").data(data).exit().remove()

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

            svg.append("g")
                .attr("class", "y axis")
                .call(yAxis)
                .append("text")
                .attr("transform", "rotate(-90)")
                .attr("y", 6)
                .attr("dy", ".71em")
                .style("text-anchor", "end")
                .text("Tasks");

            var person_name = svg.selectAll(".name")
                .data(data)
                .enter().append("g")
                .attr("transform", function(d) { return "translate(" + x(d.Name) + ",0)"; });

            person_name.selectAll("rect")
                .data(function(d) { return d.tasks; })
                .enter().append("rect")
                .attr("width", x.rangeBand())
                .attr("y", function(d) { return y(d.y1); })
                .attr("height", function(d) { return y(d.y0) - y(d.y1); })
                .style("fill", function(d) { return color(d.category); });

            console.log(svg.selectAll(".name").data(data).exit());

            var legend = svg.selectAll(".legend")
                .data(color.domain().slice().reverse())
                .enter().append("g")
                .attr("class", "legend")
                .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

            legend.append("rect")
                .attr("x", width - 18)
                .attr("width", 18)
                .attr("height", 18)
                .style("fill", color);

            legend.append("text")
                .attr("x", width - 24)
                .attr("y", 9)
                .attr("dy", ".35m")
                .style("text-anchor", "end")
                .text(function(d) { return d; });

        });
    };

    updateMultiData(initial_csv_url);

    $(document).on("click", "button.update_d3_csv", function(e){
        e.preventDefault();
        var new_info = $("#id_date_form").serialize(),
            new_multi_csv_url = "{% url blahblah %}?" + new_info;
        updateMultiData(new_multi_csv_url);
        console.log(new_multi_csv_url);
    });
</script>
4

1 に答える 1

3

上記の例では、入力されたノードにはクラスが定義されていないようです。それ以降d3.selectAll(".name")は空の選択が返され、すべてのデータ要素が.enter()メソッドの下に表示されます。

入力ノードが追加されるたびに、対応するクラス名を割り当ててみることをお勧めします。

.enter().append("g").classed("name",true)

の 2 番目の引数を使用し.data()て各データポイントの一意の識別子 (キー) を定義し、順序が異なる場合に更新ごとに正しい要素が終了されるようにすることも検討してください。 https://github.com/mbostock/d3/wiki/Selections#wiki-data

あなたのコードでは、「name」プロパティはおそらくキーとして使用できます:

var person_name = svg.selectAll(".name")
            .data(data,function(d) { return d.name; })

最後に、更新関数内に軸を追加していることに気付きました。これは、更新ごとに新しい軸のセットが以前のものの上に追加されることを意味します。それらを最上位に移動したい場合があります。

于 2013-03-20T21:25:05.517 に答える