Настройте линии сетки в гистограмме d3 - PullRequest
0 голосов
/ 20 февраля 2020

Я занимаюсь разработкой двусторонней гистограммы, используя d3. Я хочу добавить линии сетки на гистограмму, как настроить эти линии сетки. Я использовал d3f c для рисования линий сетки. Это выглядит примерно так:

var x = d3.scaleLinear()
    .rangeRound([0, width])

var y = d3.scaleBand()
    .rangeRound([0, height]).padding(0.5);

var xAxis = d3.axisBottom(x)
    .ticks(8)
    .tickSize(0)
    .tickFormat(function(d){
        return d3.format('.00s')(Math.abs(d));   // Use Math.abs() to get the absolute value
    });

var yAxis = d3.axisLeft(y)
    .ticks(5)
    .tickSize(0);
//draw grid lines
const gridline = fc.annotationSvgGridline()
    .xScale(x)
    .yScale(y);
var svg = d3.select("#ageSexNotif").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 + ")");

x.domain([-d3.max(data, function(d){
    return d.female
})*1.2,d3.max(data, function(d){
    return d.female
})*1.2])
y.domain(data.map(function (d) {
    return d.age;
}));

svg.append("g")
    .attr("class", "x axis")
    .call(xAxis)
    .call(gridline);

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

var barsRight = svg.selectAll(".bar")
    .data(data)
    .enter().append("g")

barsRight.append("rect")
    .attr("class", "bar")
    .attr("x", function (d) {
        return x(Math.min(0, d.female));
    })
    .attr("y", function (d) {
        return y(d.age);
    })
    .attr("width", function (d) {
        return Math.abs(x(d.female) - x(0));
    })
    .transition()
    .duration(1500)
    .delay(200)
    .style("margin-top", "10px")
    .attr("height", y.bandwidth())
    .attr("fill", "#F293C9")
    .attr("text", "label");

barsRight.append("text")
    .attr("class", "label")
    //y position of the label is halfway down the bar
    .attr("y", function (d) {
        return y(d.age) + y.bandwidth()- 6;
    })
    //x position is 3 pixels to the right of the bar
    .attr("x", function (d) {
        return x(d.female) + 10;
    })
    .text(function (d) {
        return (d.female/1000)+'k';
    })
    .style("font-family", "Source Sans Pro")
    .style("font-size", "14px")
    .style("font-weight", "bold")
    .attr("fill", "#F293C9");  


var barsLeft = svg.selectAll(".bar2")
    .data(data)
    .enter().append("g")

barsLeft.append("rect")
    .attr("class", "bar2")
    .attr("x", function (d) {
        return x(Math.min(0, -d.male));
    })
    .attr("y", function (d) {
        return y(d.age);
    })
    .attr("width", function (d) {
        return Math.abs(x(-d.male) - x(0));
    })
    .transition()
    .duration(1500)
    .delay(200)
    .style("margin-top", "10px")
    .attr("height", y.bandwidth())
    .attr("fill", "#4880FF");

barsLeft.append("text")
    .attr("class", "label")
    .style("font-family", "Source Sans Pro")
    .style("font-size", "14px")
    .style("font-weight", "bold")
    .attr("fill","#4880FF")
    //y position of the label is halfway down the bar
    .attr("y", function (d) {
        return y(d.age) + y.bandwidth()- 6;
    })
    //x position is 3 pixels to the right of the bar
    .attr("x", function (d) {
        return x(-d.male) - 40;
    })
    .text(function (d) {
        return (d.male/1000)+'k';
    });

Результат моего графика равен

image

Мой график должен выглядеть следующим образом

image

Как соединить края по оси X и выделить базовую ось, как показано на рисунке? Любая помощь для настройки линий сетки приветствуется. Ссылка на мой пример ссылка

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Я внес в вашу ручку некоторые изменения, которые вы можете увидеть здесь .

Основные изменения:

соединить края по оси x

Если вы удалите множитель *1.2 из доменов и добавите .nice(), то ось x будет возведена в квадрат с линиями сетки.

var x = d3.scaleLinear()
   .rangeRound([0, width])
   .domain([-d3.max(data, d => d.female), d3.max(data, d => d.female)])
   .nice();

выделите базовую ось

Мы можем сделать это, используя строку аннотации из d3f c.

const line = fc.annotationSvgLine()
  .xScale(x)
  .yScale(y)
  .orient('vertical')
  .label('')
  .decorate(selection => {
    selection.select('line')
      .attr('stroke', 'black'); 
  });
svg.datum([0]).call(line);

Здесь мы создаем линию аннотации, используя наши шкалы. Мы устанавливаем вертикальную линию и удаляем метку по умолчанию, заменяя ее пустой строкой. После этого мы используем функцию decorate, чтобы закрасить линию черным цветом.

, настраивая линии сетки

Мы можем контролировать прозрачность линий сетки, используя функцию decorate .

const opacityDecorate = selection => {
  selection.attr('opacity', 0.2);
};

const gridline = fc.annotationSvgGridline()
          .xScale(x)
          .yScale(y)
          .xDecorate(opacityDecorate)
          .yDecorate(opacityDecorate);

Здесь мы используем функцию декорации, чтобы установить непрозрачность для горизонтальной и вертикальной линий сетки. В качестве альтернативы вы также можете использовать разные функции декорирования для различного стиля горизонтальных и вертикальных линий.

Надеюсь, это поможет!

1 голос
/ 20 февраля 2020

Вы можете добавить имя класса к линиям сетки, используя attr('class', 'class-name'), и добавить свой эффект с помощью CSS.

...