Angular 6 и D3 v.5.5, это. <variable>не определено - PullRequest
0 голосов
/ 08 февраля 2019

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

Функция updateChart сработает после того, как я нажму на панель.Затем я увижу эту ошибку в консоли:

Ошибка при щелчке панели

Я попытался «сохранить» переменные в объекте и импортировать его.После этого я попытался дать им значение в конструкторе, как я видел здесь: Typescript: получение неопределенного значения , но ничего не получалось.

Мой код является разновидностью этого плункера: https://stackblitz.com/edit/angular-d3-v4-barchart?file=app%2Fshared%2Fbarchart%2Fbarchart.component.ts

Я новичок в этом, поэтому мой код, вероятно, содержит много ошибок, но моя главная проблема - использовать переменные в функции updateChart,

import { Component, OnInit, ViewChild, ElementRef, Input, 

ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
import { IHierarchyDatum } from './IHierarchyDatum';
import { HierarchyNode } from 'd3-hierarchy';
import { Agp } from '../agp';

@Component({
  selector: 'app-d3-agp',
  templateUrl: './d3-agp.component.html',
  styleUrls: ['./d3-agp.component.css'],
  encapsulation: ViewEncapsulation.None
})

export class D3AgpComponent implements OnInit {

  @ViewChild('chart') private chartContainer: ElementRef;
  private margin: any = { top: 20, bottom: 20, left: 20, right: 20 };
  private chart: any;
  private width: number;
  private height: number;
  private xScale: any;
  private yScale: any;
  private colors: any;
  private xAxis: any;
  private yAxis: any;
  help: IHierarchyDatum;

  constructor (public agp: Agp) {
  }

  ngOnInit () {

    d3.json('http://localhost:3000/posts')
      .then((data: IHierarchyDatum) => {
        if (data) {
          this.help = data;
          this.createChart();
        }
      })
      .catch((err) => {
        console.log(err);
      });
  }

  createChart () {
    let root = d3.hierarchy(this.help[0], function (d) {
      return d.children;
    });
    root = root.sum(function (d) {
      return d.size;
    });
    const element = this.chartContainer.nativeElement;
    this.width = element.offsetWidth - this.margin.left - this.margin.right;
    this.height = element.offsetHeight - this.margin.top - this.margin.bottom;
    const svg = d3.select(element).append('svg')
      .attr('width', element.offsetWidth)
      .attr('height', element.offsetHeight);


    this.chart = svg.append('g')
      .attr('class', 'bars')
      .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
    const xDomain = root.children.map(d => d.data.name);
    const yDomain = [0, d3.max(root.children, d => d.value)];

    this.xScale = d3.scaleBand().padding(0.1).domain(xDomain).rangeRound([0, this.width]);
    this.yScale = d3.scaleLinear().domain(yDomain).range([this.height, 0]);

    this.colors = d3.scaleLinear().domain([0, root.children.length]).range(<any[]>['red', 'blue']);

    this.xAxis = svg.append('g')
      .attr('class', 'xAxis')
      .attr('transform', `translate(${this.margin.left}, ${this.margin.top + this.height})`)
      .call(d3.axisBottom(this.xScale));

    this.yAxis = svg.append('g')
      .attr('class', 'yAxis')
      .attr('transform', `translate(${this.margin.left}, ${this.margin.top})`)
      .call(d3.axisRight(this.yScale));

    this.updateChart(root);
  }

  updateChart (root: HierarchyNode<IHierarchyDatum>) {

    this.xScale.domain(root.children.map(d => d.data.name));
    this.yScale.domain([0, d3.max(root.children, d => d.value)]);
    this.colors.domain([0, root.children.length]);
    this.xAxis.transition().call(d3.axisBottom(this.xScale));
    this.yAxis.transition().call(d3.axisLeft(this.yScale));

    const update = this.chart.selectAll('.bar')
      .data(root.children)
      .enter()
      .append('rect')
      .attr('class', 'bar')
      .attr('x', d => this.xScale(d.data.name))
      .attr('y', d => this.yScale(0))
      .attr('width', this.xScale.bandwidth())
      .attr('height', 0)
      .style('fill', (d, i) => this.colors(i))
      .transition()
      .delay((d, i) => i * 10)
      .attr('y', d => this.yScale(d.value))
      .attr('height', d => this.height - this.yScale(d.value));

    this.chart.selectAll('rect')
      .on('click', this.updateChart);
  }
}

1 Ответ

0 голосов
/ 17 апреля 2019

У меня была та же проблема с моим кодом D3 с угловым значением

Когда вы связываете функцию в D3 внутри обработчика событий, ваш контекст this является объектом, в котором вы находитесь (например, прямоугольник, если оннаведите курсор мыши на прямоугольник, ...), чтобы сохранить свой угловой контекст, вы должны связать свою ссылку на функцию следующим образом:

// your code above
  this.chart.selectAll('rect')
  .on('click', this.updateChart);
  } // end of your function which create your element

public updateChart = () => {
   //your code to update your chart
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...