Angular 角度6和D3第5.5节,本节。<;变量>;未定义

Angular 角度6和D3第5.5节,本节。<;变量>;未定义,angular,typescript,d3.js,Angular,Typescript,D3.js,目前,我正在尝试用D3在我的Angular应用程序中构建一个层次条形图。如果我点击一个条,我想递归地使用我的函数来重塑我的图表。第一个初始调用工作得很好,但在我单击一个条后,变量未定义 函数updateChart将在我单击一个条后启动。我将在控制台中看到此错误,然后: 我试图在对象中“保存”变量并导入它。之后,我尝试在构造函数中给它们一个值,就像我在这里看到的: ,但没有任何效果 我的代码是这个plunker的变体: 我是新手,所以我的代码可能有很多错误,但我的主要问题是在updateCha

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

函数updateChart将在我单击一个条后启动。我将在控制台中看到此错误,然后:

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

我的代码是这个plunker的变体:

我是新手,所以我的代码可能有很多错误,但我的主要问题是在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);
  }
}
import{Component,OnInit,ViewChild,ElementRef,Input,
来自“@angular/core”的视图封装};
从“d3”导入*作为d3;
从“/IHierarchyDatum”导入{IHierarchyDatum};
从“d3层次结构”导入{HierarchyNode};
从“../Agp”导入{Agp};
@组成部分({
选择器:“app-d3-agp”,
templateUrl:'./d3 agp.component.html',
样式URL:['./d3 agp.component.css'],
封装:视图封装。无
})
导出类D3AGP组件实现OnInit{
@ViewChild(“图表”)私有图表容器:ElementRef;
私有边距:any={顶部:20,底部:20,左侧:20,右侧:20};
私人海图:任何;
私有宽度:数字;
私人身高:数字;
私人xScale:任何;
私人规模:任何;
私人色彩:任何;
私人xAxis:任何;
私人雅克斯:任何;
帮助:IHierarchyDatum;
建造商(公共agp:agp){
}
恩戈尼尼特(){
d3.json('http://localhost:3000/posts')
.然后((数据:IHierarchyDatum)=>{
如果(数据){
this.help=数据;
这个.createChart();
}
})
.catch((错误)=>{
控制台日志(err);
});
}
createChart(){
设root=d3.hierarchy(this.help[0],函数(d){
返回d.儿童;
});
root=root.sum(函数(d){
返回d.size;
});
常量元素=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('高度',元素.离视);
this.chart=svg.append('g')
.attr('class','bar')
.attr('transform','translate(${this.margin.left},${this.margin.top})`);
const xDomain=root.children.map(d=>d.data.name);
常量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(['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(根:HierarchyNode){
this.xScale.domain(root.children.map(d=>d.data.name));
这个.yScale.domain([0,d3.max(root.children,d=>d.value)];
this.colors.domain([0,root.children.length]);
调用(d3.axisBottom(this.xScale));
this.yAxis.transition().call(d3.axisLeft(this.yScale));
const update=this.chart.selectAll(“.bar”)
.data(root.children)
.输入()
.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)=>此.colors(i))
.transition()
.延迟((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);
}
}

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

当您在D3中绑定一个函数时,在事件处理程序中,您的this上下文就是您所在的对象(例如,如果鼠标位于rect上,则为rect…),为了保持角度上下文,您必须将您的foction链接绑定到此

// 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
}

我希望它能帮助你

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

当您在D3中绑定一个函数时,在事件处理程序中,您的this上下文就是您所在的对象(例如,如果鼠标位于rect上,则为rect…),为了保持角度上下文,您必须将您的foction链接绑定到此

// 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
}
我希望这对你有帮助