Как я могу переместить линию сетки за гистограммой (D3) - PullRequest
0 голосов
/ 25 апреля 2018

Я хочу переместить линию сетки за гистограммой, на самом деле я печатаю линии сетки перед барами в функции upgradeChart (), есть предложения?Мне нужны линии сетки :) Я не могу их удалить.Вот мой код:

    import { Component, OnInit, OnChanges, ViewChild, ElementRef, AfterViewInit, ViewEncapsulation, Input } from '@angular/core';
import * as d3 from 'd3';
import * as _d3Tip from 'd3-tip';

@Component({
  selector: 'app-histogram',
  templateUrl: './histogram.component.html',
  styleUrls: ['./histogram.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class HistogramComponent implements OnInit, OnChanges {
   @ViewChild('chart') private chartContainer: ElementRef;
   @Input() public config;
    private chart;
    private margin;
    private width;
    private height;
    private xScale;
    private yScale;
    private xAxis;
    private yAxis;
    private element;
    private svg;

  constructor() {
  }

  ngOnInit() {
    console.log(this.config);
    this.createChart( );
    if (this.config.data) {
      this.updateChart();
    }
  }

  ngOnChanges() {
    if (this.chart) {
      this.updateChart();
    }
  }

  public createChart() {

// Traemos el elemento donde estará el gráfico en este caso #chart
this.element = this.chartContainer.nativeElement;

// Guardamos los datos en una constante
const data = this.config.data;

// Declaramos el margen, el ancho y la altura del gráfico según los estilos del div #chart (d3-chart)
this.margin = { top: 40, right: 20, bottom: 30, left: 40 };
this.width = this.element.offsetWidth - this.margin.left - this.margin.right;
this.height = this.element.offsetHeight - this.margin.top - this.margin.bottom;

this.svg = d3.select(this.element).append('svg')
  .attr('width', this.element.offsetWidth)
  .attr('height', this.element.offsetHeight);

// chart plot area
this.chart = this.svg.append('g')
  .attr('class', 'bars')
  .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);

// Creamos las escalas
this.xScale = d3.scaleBand().range([0, this.width]).padding(0.3);
this.yScale = d3.scaleLinear().range([this.height, 0]);

// Definimos la posicion del eje X en la parte de abajo
this.xAxis = this.svg.append('g')
  .attr('class', 'x axis')
  .attr('transform', `translate(${this.margin.left}, ${this.margin.top + this.height})`)
  .call(d3.axisBottom(this.xScale));

// Definimos la posicion del eje Y en la parte izquierda con su formato..
this.yAxis = this.svg.append('g')
  .attr('class', 'y axis')
  .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`)
  .call(d3.axisLeft(this.yScale));


 }

  public updateChart() {

// Necesario al importar la libreria d3-tip para versiones superiores a 4 en d3.js
const d3Tip = _d3Tip.bind(d3);

// Creamos el tooltip
const tip = d3Tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
  return '<span class="highlight">' + d.valueY + '€' + '</span>';
});

this.svg.call(tip);

// Definimos los datos de las escalas
this.xScale.domain(this.config.data.map( d => d.valueX));
this.yScale.domain([0, d3.max(this.config.data, d => d.valueY)]);
this.xAxis.transition().call(d3.axisBottom(this.xScale));
this.yAxis.transition().call(d3.axisLeft(this.yScale).tickSize(-this.width).ticks(4).tickFormat(d => d + '€'));

const update = this.chart.selectAll('.bar')
  .data(this.config.data);

  // remove exiting bars
  update.exit().remove();

  // update existing bars
  this.chart.selectAll('.bar').transition()
    .attr('x', d => this.xScale(d.valueX))
    .attr('y', d => this.yScale(d.valueY))
    .attr('width', d => this.xScale.bandwidth())
    .attr('height', d => this.height - this.yScale(d.valueY));

    update
    .enter().append('rect')
    .attr('class', 'bar')
    .attr('data-index', function(d, i) { return i; })
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide)
    .attr('x', d => this.xScale(d.valueX))
    .attr('y', d => this.yScale(d.valueY))
    .attr('width', this.xScale.bandwidth())
    .transition()
    .ease(d3.easeLinear)
    .duration(300)
    .delay((d, i) => i * 50)
    .attr('height', d => this.height - this.yScale(d.valueY));


 }

}

Проблема в этой строке:

this.yAxis.transition().call(d3.axisLeft(this.yScale).tickSize(-this.width).ticks(4).tickFormat(d => d + '€'));

Эта строка делает линию сетки:

.tickSize(-this.width).ticks(4).tickFormat(d => d + '€')

Я даю одну картинку из моегоbarChart Линейчатая диаграмма d3.js v5

РЕШЕНИЕ ДЛЯ РЕШЕТКИ:

решение заключается в следующем:

    // chart plot area
this.chart = this.svg.append('g')
.attr('class', 'bars')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);

после этого:

    // Definimos la posicion del eje Y en la parte izquierda con su formato..
this.yAxis = this.svg.append('g')
  .attr('class', 'y axis')
  .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`)
  .call(d3.axisLeft(this.yScale));

Редактировать: еще вопросы:

  1. Кто-то знает, как может реагировать мой гистограмма?
  2. Мне нужно поставить минимальный бар, когда значение равно 0 €, как я могу это сделать?

1 Ответ

0 голосов
/ 25 апреля 2018

Я не уверен без скрипки, но у svg изначально не было z-index.Элементы были наслоены на основе дерева DOM.Так что последний розыгрыш показан сверху.В вашем случае я вижу:

this.xAxis = this.svg.append('g')...

и

this.yAxis = this.svg.append('g')..

Теперь вместо того, чтобы добавлять их как элементы g непосредственно в svg, вы бы попытались создать оболочку g для обеих осей:

this.wrapper = this.svg.append('g');

затем вместо вышеуказанных 2 выполните:

this.xAxis = this.wrapper.append('g')...

Убедитесь, что элемент g обертки добавлен, прежде чем добавлять ваши elements.does, которые уменьшают проблему?

Для других ваших вопросов,

2 - есть несколько способов сделать его отзывчивым, один из самых простых - использовать атрибут preserveAspectRatio = "none" в вашем svg, а затем контролировать div или любой элемент, который оборачиваетваш svg, используя css медиа-запросы.Если вы имеете в виду изменение способа отрисовки осей и т. Д., То вам нужно вызвать функцию обновления, которая обновит эти элементы в окне "resize" событие.

3 - используйте Math.max и Math.min при настройкеваши высоты x, y или width или преобразуйте атрибуты на графике, например

.attr("height",function(d,i){return Math.min(someMin,someScale(d))})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...