d3图表有两个传奇问题

时间:2016-04-12 08:33:13

标签: json d3.js

我有一个在d3中构建的图表,用于显示在演讲过程中谁在说话以及在哪里。字符用颜色条表示,我想提供一个图例。但是,我的图例代码会垂直显示在单个列中,并多次显示相同的字符名称。我知道后者是因为它正在解析json中的每条记录,但是我不知道如何只提供一个字符而不是提供一个字符列表,就像我在代码中提供一个位置列表一样。我有办法从json那里做到这一点吗?

另外,如何在网格中组织图例以利用图表左上角的空白区域?我创建了一个小提琴,其中包含我目前在https://jsfiddle.net/3f7xrgeb/处的代码,并在下面粘贴了它。我的工作副本(如果小提琴没有显示)位于http://www.matthewedavis.net/Magdalene_playtext/test_bars.html

任何帮助将不胜感激。

    var margin = {top: 50, right: 150, bottom: 50, left: 150},
        w = 2500 - margin.left - margin.right,
        h = 500 - margin.top - margin.bottom;

    d3.json("http://www.matthewedavis.net/Magdalene_playtext/test_chart.json", function(json) {

        var data = json.items;

        var test = function(d) { return d.starting_line + d.duration; };

        var stage_directions = ([44, 49, 114, 140, 209, 217, 249, 257, 265, 277, 305, 334, 358, 381, 398, 409, 440, 470, 491, 547, 555, 564, 572, 587, 614, 630, 640, 691, 704, 725, 743, 775, 793, 818, 823, 841, 845, 868, 872, 888, 902, 910, 920, 925, 963, 993, 1005, 1023, 1031, 1047, 1061, 1096, 1125, 1133, 1143, 1178, 1210, 1228, 1281, 1293, 1336, 1349, 1376, 1395, 1439, 1446, 1454, 1538, 1554, 1562, 1578, 1598, 1610, 1618, 1642, 1646, 1716, 1725, 1743, 1781, 1791, 1797, 1843, 1863, 1887, 1915, 1923, 1939 ,1972, 1989, 2019, 2031, 2039, 2045, 2073, 2085, 2101, 2123])

        var x = d3.scale.linear()
        .domain([0, 2200])
        .range([0, w]);

        var y = d3.scale.ordinal()
        .domain(["The priest's cell","The Cloud","Wilderness","The mountain","The Lodge","Marseilles","The Ship","Heaven","Heathen Temple","Sepulchre","The Stations","Palace of the King of Marseilles","Lazarus' tomb","Simon the Leper's House","Arbor","Jherusalem","Tavern","Hellmouth","The Place","Stage Above Hell","King of Flesh's location","King of the World's location","Pilate's location","Herod's location","Magdalene Castle","Tiberius' Palace"])
        .rangeBands([0, h]);

        var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

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

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

        svg.append("text") 
        .attr("transform", "translate(" + (w / 2) + " ," + (h + margin.bottom - 5) +")")
        .style("text-anchor", "middle")
        .text("Line Number");

        var t;
        for (t in stage_directions){
        svg.append("rect")
        .attr("class", "overlay")
        .attr("x",stage_directions[t])
        .attr("width", 1)
        .attr("height", h)
        .style ("fill", "black")
        .style ("opacity", 0.3);
    }

        svg.append("rect")
        .attr("class", "overlay")
        .attr("x",1)
        .attr("width", 1133)
        .attr("height", h)
        .style ("fill", "red")
        .style ("opacity", 0.1);

        svg.append("rect")
        .attr("class", "overlay")
        .attr("x",1133)
        .attr("width", 857)
        .attr("height", h)
        .style ("fill", "yellow")
        .style ("opacity", 0.1);

        svg.append("rect")
        .attr("class", "overlay")
        .attr("x",1990)
        .attr("width", 134)
        .attr("height", h)
        .style ("fill", "green")
        .style ("opacity", 0.1);

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

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

        var bars = svg.selectAll(".bar")
        .data(data)
        .enter()
        .append("rect")
        .attr("class", function(d, i) {return "bar " + d.character;})
        .attr("x", function(d, i) {return d.starting_line;})
        .attr("y", function(d, i) {return y(d.location);})
        .attr("width", function(d, i) {return d.duration;})
        .attr("height", 15)
        .style("fill", function(d,i) {return "#" + d.color;});


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

        legend.append("rect")
        .attr("x", 10)
        .attr("width", 10)
        .attr("height", 10)
        .style("fill", function(d,i) {return "#" + d.color;});

        legend.append("text")
        .attr("x", 22)
        .attr("y", 5)
        .attr("dy", ".35em")
        .text(function(d) { return d.character; });

        svg.append("g")
        .attr("class", "legend")
        .call(legend)
    });

1 个答案:

答案 0 :(得分:0)

试试这个:

首先,创建一个包含字符列表的数组,避免重复:

var listCharacters = d3.set(data.map(function(d){ return d.character})).values();

然后,将其用作图例的数据:

var legend = svg.selectAll(".legend")
.data(listCharacters)
.enter()
//the test of the code...

然后更改text

.text(function(d,i){ return listCharacters[i]});

对于颜色,请执行相同的操作:

var listColors = d3.set(data.map(function(d){ return d.colour})).values(); //check the spelling in your object

根据索引为矩形着色:

.attr("fill", function(d,i){ return listColors[i]});

要了解它的作用,请阅读: https://github.com/mbostock/d3/wiki/Arrays