d3 v4 和 angular v4 直方图语法
d3 v4 and angular v4 histogram syntax
我正在为 d3 直方图构建一个非常简单的 angular 控件。
我在网上看了很多教程,他们似乎都在建议构建直方图 bins 的特定语法:
let datagenerator = d3.histogram<number>()
.domain(d => x.domain())
.thresholds(x.ticks(20));
let bins = datagenerator(this.data);
当我尝试此操作时,出现以下错误:
ERROR in src/app/d3/histogram/histogram.component.ts (45,25):
Supplied parameters do not match any signature of call target.
更新:尝试以下建议后,我取得了进步,但现在出现此错误:
ERROR in src/app/d3/histogram/histogram.component.ts (48,15): Argument of type '(d: number[]) => number[]' is not assignable to parameter of type '(values: number[]) => [number, number]'.
Type 'number[]' is not assignable to type '[number, number]'.
Property '0' is missing in type 'number[]'.
ERROR in src/app/d3/histogram/histogram.component.ts (54,15): Argument of type '(string | number)[]' is not assignable to parameter of type '(number | { valueOf(): number; })[]'.
Type 'string | number' is not assignable to type 'number | { valueOf(): number; }'.
Type 'string' is not assignable to type 'number | { valueOf(): number; }'.
ERROR in src/app/d3/histogram/histogram.component.ts (54,48): Property 'length' does not exist on type '{}'.
这是完整的来源:
import { Component, OnInit, OnChanges, ViewChild, ElementRef, Input,
ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
@Component({
selector: 'histogram',
templateUrl: './histogram.component.html',
styleUrls: ['./histogram.component.css'],
encapsulation: ViewEncapsulation.None
})
export class HistogramComponent implements OnInit {
@ViewChild('chart') private chartContainer:ElementRef;
@Input() private histogramdata:Array<number>;
private margin:any = {top: 20, bottom: 20, left: 20, right: 20};
private chart:any;
private svg:any;
private width;
private height;
private data;
constructor() { }
createChart() {
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);
// chart plot area
this.chart = this.svg.append('g')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
}
updateChart() {
let formatCount = d3.format(",.0f");
//this.data = this.histogramdata;
this.data = [0.1,0.2,0.3,0.4];
let x = d3.scaleLinear<number>()
.rangeRound([0, this.width]);
let datagenerator = d3.histogram<number, number>()
.domain(d => x.domain())
.thresholds(x.ticks(20));
let bins = datagenerator(this.data);
let y = d3.scaleLinear<number>()
.domain([0, d3.max(bins, d => { return d.length; })])
.range([this.height, 0]);
let bar = this.chart.selectAll(".bar")
.data(bins)
.enter().append("g")
.attr("class", "bar")
.attr("transform", d => {
return "translate(" + x(d.x0) + "," + y(d.length) + ")";
});
let barWidth = x(bins[0].x1) - x(bins[0].x0) - 1;
bar.append("rect")
.attr("x", 1)
.attr("width", barWidth)
.attr("height", d => { return this.height - y(d.length); });
let textLoc = (x(bins[0].x1) - x(bins[0].x0)) / 2;
bar.append("text")
.attr("dy", ".75em")
.attr("y", 6)
.attr("x", textLoc)
.attr("text-anchor", "middle")
.text(d => { return formatCount(d.length); });
this.chart.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + this.height + ")")
.call(d3.axisBottom(x));
}
ngOnInit() {
}
}
我知道我们必须在调用中添加一些类型装饰器以实现 typescript 兼容性,但我不明白的是为什么错误提示直方图函数应采用参数。我见过的所有例子都没有参数。
感谢您的浏览。任何建议表示赞赏。
d3.histogram<number, number>()
用于数字数组。
或:
d3.histogram<MixedObject, number | Date>()
其中 "Mixed Object" 是与您的数据匹配的自定义类型,并且您按数字或日期分箱。
为了进一步提供帮助,请使用您的数据样本更新您的问题...
编辑
再次查看源代码。这很容易理解。第一个参数是您要用来调用直方图函数的数组中的类型。它被使用,例如在 value
函数中,如:
.value(( d: number, i: number ) => {
return d;
})
第二种是设置两部分为domain
时使用的类型和数组中指定为阈值的类型。它还在 return 对象中用作 x0
和 x1
属性的类型。
综上所述,我只是在 Angular2/Typescript 中做了一个简单的测试:
let dataGenerator = d3.histogram<number, number>()
.thresholds([0.2,0.4,0.6,0.8,1]);
let data = d3.range(100).map(() => {
return Math.random();
});
console.log(dataGenerator(data));
它既能构建又能构建 运行。
为了进一步提供帮助,请提供一套完整的代码来重现您的问题。
编辑 2
错误其实在这里:
let datagenerator = d3.histogram<number, number>()
.domain(d => x.domain()) //<-- ERROR
.thresholds(x.ticks(20));
x.domain()
returns number[]
,而 histogram<number, number().domain(
期待 [number, number]
.
我会这样整理:
let dom : number[] = x.domain();
let datagenerator = d3.histogram<number, number>()
.domain([ dom[0], dom[1] ])
.thresholds(x.ticks(20));
我正在为 d3 直方图构建一个非常简单的 angular 控件。
我在网上看了很多教程,他们似乎都在建议构建直方图 bins 的特定语法:
let datagenerator = d3.histogram<number>()
.domain(d => x.domain())
.thresholds(x.ticks(20));
let bins = datagenerator(this.data);
当我尝试此操作时,出现以下错误:
ERROR in src/app/d3/histogram/histogram.component.ts (45,25):
Supplied parameters do not match any signature of call target.
更新:尝试以下建议后,我取得了进步,但现在出现此错误:
ERROR in src/app/d3/histogram/histogram.component.ts (48,15): Argument of type '(d: number[]) => number[]' is not assignable to parameter of type '(values: number[]) => [number, number]'.
Type 'number[]' is not assignable to type '[number, number]'.
Property '0' is missing in type 'number[]'.
ERROR in src/app/d3/histogram/histogram.component.ts (54,15): Argument of type '(string | number)[]' is not assignable to parameter of type '(number | { valueOf(): number; })[]'.
Type 'string | number' is not assignable to type 'number | { valueOf(): number; }'.
Type 'string' is not assignable to type 'number | { valueOf(): number; }'.
ERROR in src/app/d3/histogram/histogram.component.ts (54,48): Property 'length' does not exist on type '{}'.
这是完整的来源:
import { Component, OnInit, OnChanges, ViewChild, ElementRef, Input,
ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
@Component({
selector: 'histogram',
templateUrl: './histogram.component.html',
styleUrls: ['./histogram.component.css'],
encapsulation: ViewEncapsulation.None
})
export class HistogramComponent implements OnInit {
@ViewChild('chart') private chartContainer:ElementRef;
@Input() private histogramdata:Array<number>;
private margin:any = {top: 20, bottom: 20, left: 20, right: 20};
private chart:any;
private svg:any;
private width;
private height;
private data;
constructor() { }
createChart() {
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);
// chart plot area
this.chart = this.svg.append('g')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
}
updateChart() {
let formatCount = d3.format(",.0f");
//this.data = this.histogramdata;
this.data = [0.1,0.2,0.3,0.4];
let x = d3.scaleLinear<number>()
.rangeRound([0, this.width]);
let datagenerator = d3.histogram<number, number>()
.domain(d => x.domain())
.thresholds(x.ticks(20));
let bins = datagenerator(this.data);
let y = d3.scaleLinear<number>()
.domain([0, d3.max(bins, d => { return d.length; })])
.range([this.height, 0]);
let bar = this.chart.selectAll(".bar")
.data(bins)
.enter().append("g")
.attr("class", "bar")
.attr("transform", d => {
return "translate(" + x(d.x0) + "," + y(d.length) + ")";
});
let barWidth = x(bins[0].x1) - x(bins[0].x0) - 1;
bar.append("rect")
.attr("x", 1)
.attr("width", barWidth)
.attr("height", d => { return this.height - y(d.length); });
let textLoc = (x(bins[0].x1) - x(bins[0].x0)) / 2;
bar.append("text")
.attr("dy", ".75em")
.attr("y", 6)
.attr("x", textLoc)
.attr("text-anchor", "middle")
.text(d => { return formatCount(d.length); });
this.chart.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + this.height + ")")
.call(d3.axisBottom(x));
}
ngOnInit() {
}
}
我知道我们必须在调用中添加一些类型装饰器以实现 typescript 兼容性,但我不明白的是为什么错误提示直方图函数应采用参数。我见过的所有例子都没有参数。
感谢您的浏览。任何建议表示赞赏。
d3.histogram<number, number>()
用于数字数组。
或:
d3.histogram<MixedObject, number | Date>()
其中 "Mixed Object" 是与您的数据匹配的自定义类型,并且您按数字或日期分箱。
为了进一步提供帮助,请使用您的数据样本更新您的问题...
编辑
再次查看源代码。这很容易理解。第一个参数是您要用来调用直方图函数的数组中的类型。它被使用,例如在 value
函数中,如:
.value(( d: number, i: number ) => {
return d;
})
第二种是设置两部分为domain
时使用的类型和数组中指定为阈值的类型。它还在 return 对象中用作 x0
和 x1
属性的类型。
综上所述,我只是在 Angular2/Typescript 中做了一个简单的测试:
let dataGenerator = d3.histogram<number, number>()
.thresholds([0.2,0.4,0.6,0.8,1]);
let data = d3.range(100).map(() => {
return Math.random();
});
console.log(dataGenerator(data));
它既能构建又能构建 运行。
为了进一步提供帮助,请提供一套完整的代码来重现您的问题。
编辑 2
错误其实在这里:
let datagenerator = d3.histogram<number, number>()
.domain(d => x.domain()) //<-- ERROR
.thresholds(x.ticks(20));
x.domain()
returns number[]
,而 histogram<number, number().domain(
期待 [number, number]
.
我会这样整理:
let dom : number[] = x.domain();
let datagenerator = d3.histogram<number, number>()
.domain([ dom[0], dom[1] ])
.thresholds(x.ticks(20));