D3.jsナビゲーションバーを作成する角度(angular2/angular4ではなくangularJS)コンポーネントを構築しています。私は他のD3チャートに問題はありませんでしたが、最初はうまくレンダリングされましたが、 "ブラシ"が実行されたときにクラス変数の1つにアクセスしようとするとランタイムエラーが発生します。 (サイドノート:一般的なJavascriptのD3ブラシの実装例については、この参照:https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172)'未定義は関数ではありません'実行時に角2/Typescript関数
を誤りとはいえ角度/活字体ではなくD3に関連すると表示されます。 「未定義は関数ではありません」にアクセスしようとすると "下のコードの "brushed()"関数の "this.x"を参照してください。
誰もが、私はそれが重要な場合は、「ブラッシング()」機能
import { Component, OnInit, OnChanges, ViewChild, ElementRef, Input, ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
import {StockData} from "../../dataServices/stockData";
@Component({
selector: 'app-navchart',
templateUrl: './navchart.component.html',
styleUrls: ['./navchart.component.css'],
encapsulation: ViewEncapsulation.None
})
export class NavchartComponent implements OnInit, OnChanges {
@ViewChild('chart') public chartContainer: ElementRef;
@Input() public stockdata: StockData;
public margin: any = { top: 20, bottom: 20, left: 20, right: 20};
public width : number;
public height: number;
public svg: any;
public g: any;
public chart: any;
public x: any;
public y: any;
public navline: any;
public navarea: any;
public data: any;
public brush: any;
constructor() { }
ngOnInit() {
console.log("Inside the charting - updating the data");
if (this.stockdata) {
//console.log(JSON.stringify(this.stockdata));
this.data = this.stockdata.stocklist;
setTimeout(() => {
this.initChart();
this.drawAxis();
this.drawRange();
}, 500);
}
}
ngOnChanges() {
}
public initChart(): void {
let element = this.chartContainer.nativeElement;
this.width = element.offsetWidth - this.margin.left - this.margin.right;
this.height = element.offsetHeight - this.margin.top - this.margin.bottom;
this.svg = d3.select(element).append('svg')
.attr('width', element.offsetWidth)
.attr('height', element.offsetHeight);
this.g = this.svg.append('g')
.attr("transform", "translate(" + this.margin.left + "," + this.margin.top +")");
// x and y scale functions - called every time a value needs converted to pixel location
//this will need moved to a "redraw" function when adjustments to overall chart size are allowed
this.x = d3.scaleTime()
.range([0, this.width]);
this.x.domain(d3.extent(this.data, (d: any) => new Date(d.date)));
this.y = d3.scaleLinear()
.range([this.height, 0]);
//sets the limits of x and y data.
// this will need to be moved to a redraw when changes to dataset ranges are allowed
this.y.domain([
d3.min(this.data, (d: any) => d.close),
d3.max(this.data, (d: any) => d.close)
]);
console.log ("Min = " + d3.min(this.data, (d: any) => d.close));
// line drawing functions
this.navline = d3.line()
.curve(d3.curveBasis)
.x((d: any) => this.x(new Date(d.date)))
.y((d: any) => this.y(d.close));
this.navarea = d3.area()
.curve(d3.curveBasis)
.x((d: any) => this.x(new Date(d.date)))
.y1((d: any) => this.y(d.close))
.y0((d: any) => this.height);
this.g.append("g")
.attr("class", "brush")
.call(d3.brushX().on("end", this.brushed));
}
/* Error is in this function. It cannot find "this.x" from the class,
* and gives an undefined error.
* Right now the function is just setting debug content, but when
* this.x is working, I will add .invert() to it to get the original
* date values associated with the pixel location on the x-axis.
*/
public brushed(): void {
console.log(JSON.stringify(d3.event.selection));
//returns proper [x0,x1] pixel values such as [102,500] on a svg 800 pixels wide.
let dat: any = d3.event.selection.map(this.x);
//let dat: any = d3.event.selection.map(this.x.invert) also fails with "invert does not exist on undefined"
console.log(JSON.stringify(dat));
//The error appears to be because it can't find this.x, even though that is declared and works in
// other sections of the same class.
}
//draw x and y axes
public drawAxis(): void {
this.g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + this.height + ")")
.call(d3.axisBottom(this.x));
}
public drawRange(): void {
this.g.append("path")
.attr("class", "area")
.attr("d", this.navarea(this.data));
this.g.append("path")
.attr("class", "line")
.attr("d", this.navline(this.data));
}
}
に「this.x」と「this.x.invert」にアクセスできるようにするには何をする必要があるか説明することができますデータは単に日単位の在庫エントリの配列です。
[{日付、オープン、ハイ、ロー、クローズ} ...] {"date": "2017-06-07 13:02: 「72.0700」、「72.7700」、「71.9500」、「72.0800」、「72.0800」、「volume」:「9247460」、「adjClose」:「72.6350」、 }
D3 likes "d"参照を使用する
タイピングを追加しましたか?すなわち 'npm install --save @ types/d3' – Milo
はい。私はD3.jsタイプをインストールしています。完全な 'd3'セットはtypings.d.tsで利用できます。ちょうど明らかである - チャートは実際にうまくレンダリングします。私が "ブラシ"を実行しようとするまで、エラーに当たるとは限りません。 –