Как разместить легенды для гистограммы в d3.js

Класс SimpleNamespace может использоваться для создания новых атрибутов с помощью setattr или подкласса SimpleNamespace и создания вашей собственной функции для добавления новых имен атрибутов (переменных).

from types import SimpleNamespace

variables = {"b":"B","c":"C"}
a = SimpleNamespace(**v)
setattr(a,"g","G")
a.g = "G+"
something = a.a
0
задан bisamov 24 March 2019 в 00:52
поделиться

1 ответ

В вашем коде было несколько ошибок, поэтому я попытался исправить некоторые из них.

  1. Элементы вашей диаграммы (т.е. столбцы и оси) должны быть добавлены в группу. Это позволит перемещать / переводить соответствующим образом по мере необходимости. Я создаю переменную chart и назначаю эти элементы ей, а не непосредственно svg. Это упрощает просмотр структуры при просмотре в консоли.

  2. Высота области легенды должна быть объявлена ​​и учтена в таблице. Я объявил это как переменную legendh и учел это в диапазоне оси Y.

  3. Если вы хотите, чтобы ваша группа легенд появлялась под диаграммой, ее необходимо перевести под диаграмму. В вашем предыдущем преобразовании для упомянутой группы .attr('transform', 'translate(' + (padding + 12) + ',0)'); были заданы координаты y 0. Я изменил его на .attr('transform', 'translate(' + (padding + 12) + ','+ (height - legendh) + ')');. Это говорит группе легенды двигаться вниз от вершины на величину height - legendh, таким образом, помещая ее под диаграмму.

  4. Наконец, цвета в легенде не совпадали с цветами в диаграмме / столбцах. Это было потому, что заполнение вашего бара было установлено d.key, а заполнение легенды было основано на i. Я решил сделать его равномерным и получить цвет, используя z(i).

Вот рабочий блок: https://bl.ocks.org/akulmehta/80153b35ab7498d30408f92cfa50f356

Вот рабочий код: [ 1121]

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>D3 Example</title>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
    <style>
    </style>
</head>
<style>

</style>
<body>

<div class="canvas">

</div>

<script>

    var data = [
        {month: "Q1-2016", apples: 3840, bananas: 1920, cherries: -1960},
        {month: "Q2-2016", apples: 1600, bananas: 1440, cherries: -960},
        {month: "Q3-2016", apples:  640, bananas:  960, cherries: -640},
        {month: "Q4-2016", apples:  320, bananas:  480, cherries: -640},
        {month: "Q5-2016", apples: 3840, bananas: 1920, cherries: -1960},
        {month: "Q6-2016", apples: 1600, bananas: 1440, cherries: -960},
        {month: "Q7-2016", apples:  640, bananas:  960, cherries: -640},
        {month: "Q8-2016", apples:  320, bananas:  480, cherries: -640},
        {month: "Q9-2016", apples: 3840, bananas: 1920, cherries: -1960},
        {month: "Q10-2016", apples: 1600, bananas: 1440, cherries: 960},
        {month: "Q11-2016", apples:  640, bananas:  960, cherries: -640},
        {month: "Q12-2016", apples:  320, bananas:  480, cherries: -640},
    ];

    var series = d3.stack()
        .keys(["apples", "bananas", "cherries"])
        .offset(d3.stackOffsetDiverging)
        (data);

    var margin = {top: 20, right: 30, bottom: 30, left: 60},
        width = 900,
        height = 500,
        legendh = 100, //determines the height of the legend below the chart
        padding = 40,
        svg = d3.select(".canvas").append('svg').attr('height', height).attr('width',width);

    var x = d3.scaleBand()
        .domain(data.map(function(d){return d.month;}))
        .rangeRound([margin.left, width-margin.right])
        .padding(0.1);

    var y = d3.scaleLinear()
        .domain([d3.min(series, stackMin), d3.max(series, stackMax)])
        .rangeRound([height - margin.bottom - legendh, margin.top]);

    var colors = ["#66b3ff", "#b3d9ff", "#99ddff", "#99ffdd"];
    var z = d3.scaleOrdinal(colors);

    //create and call the axes
    const xAxis = d3.axisBottom(x);
    const yAxis = d3.axisLeft(y);


    var chart = svg.append('g').attr('id','chart'); //make a chart group inside the svg

    chart.append('g')
        .selectAll('g')
        .data(series)
        .enter().append('g')
        .attr('fill', function (d,i) { //because the legend is based on i this should also be based on i
            return z(i);
        })
        .selectAll('rect')
        .data(function(d){ return d; })
        .enter().append('rect')
        .attr('width', x.bandwidth)
        .attr('x', function(d){ return x(d.data.month)})
        .attr("y", function(d) { return y(d[1]); })
        .attr("height", function(d) { return y(d[0]) - y(d[1]); })


    chart.append("g")
        .attr("transform", "translate(0," + y(0) + ")")
        .call(d3.axisBottom(x));

    chart.append("g")
        .attr("transform", "translate(" + margin.left + ",0)")
        .call(d3.axisLeft(y));

    var legend = svg.append('g')
        .attr('class', 'legend')
        .attr('transform', 'translate(' + (padding + 12) + ','+ (height - legendh)  + ')');

    legend.selectAll('rect')
        .data(series)
        .enter()
        .append('rect')
        .attr('x', 0)
        .attr('y', function(d,i){
            return i * 18;
        })
        .attr('width', 12)
        .attr('height', 12)
        .attr('fill', function(d,i){
            console.log(z(i));
            return z(i);
        });

    legend.selectAll('text')
        .data(series)
        .enter()
        .append('text')
        .text(function(d){
            return d.key;
        })
        .attr('x', 15)
        .attr('y', function(d, i){
            return i * 18;
        })
        .attr('text-anchor', 'start')
        .attr('alignment-baseline', 'hanging');



    function stackMin(serie) {
        return d3.min(serie, function(d) { return d[0]; });
    }

    function stackMax(serie) {
        return d3.max(serie, function(d) { return d[1]; });
    }




</script>
</body>
</html>
0
ответ дан Coola 24 March 2019 в 00:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: