【问题标题】:Angular 6 and D3 v.5.5, this.<variable> undefinedAngular 6 和 D3 v.5.5,this.<variable> 未定义
【发布时间】:2019-04-17 17:02:40
【问题描述】:

目前我正在尝试使用 D3 在我的 Angular 应用程序中构建层次条形图。如果我点击一个条形图,我想递归地使用我的函数来重塑我的图表。第一个初始调用完美运行,但在我单击一个栏后,变量未定义。

当我点击一个柱子后,函数 updateChart 将被触发。然后我会在控制台中看到这个错误:

Error on bar click

我尝试将变量“保存”在对象中并将其导入。之后,我试图在构造函数中给它们一个值,就像我在这里看到的那样: Typescript: getting an undefined value ,但没有任何效果。

我的代码是这个 plunker 的变体: 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);
  }
}

【问题讨论】:

    标签: angular typescript d3.js


    【解决方案1】:

    我的 D3 代码与 angular 有同样的问题

    当您在 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
    }
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      相关资源
      最近更新 更多