我在这里有一个演示
https://stackblitz.com/edit/basic-bar-mt-pjt62p?file=src%2Fapp%2Fbar-chart.ts
它是Angular应用程序中的D3条形图。
我想根据那里的高度更改条形的颜色。
我正在尝试使用d3.scaleQuantize()来做到这一点。
this.q_scale = d3.scaleQuantize()
.domain([ 600, 1000, d3.max( data, (d) => d.value) ])
.range(['blue', 'green', 'red']);
我正在传递范围内的颜色,我认为域将使用这些颜色。
小于600的条为蓝色,大于600的条为绿色,小于1000的条为红色。
d3.scaleQuantize()是执行此操作的正确方法。
如果是的话,我在做什么错
import { Component, Input, ElementRef, OnChanges, SimpleChanges, SimpleChange, ViewChild, HostListener } from "@angular/core";
import * as d3 from 'd3';
interface FLChart{
date: string,
value: number
}
@Component({
selector: 'bar-chart',
templateUrl: './bar-chart.html'
})
export class StackedChartCompoent {
@Input() data: FLChart[];
private margin = { top: 40, right: 20, bottom: 50, left: 40 };
private w: number;
private h: number = 400;
private width: number;
private height = this.h - this.margin.top - this.margin.bottom;
private x: any;
private y: any;
private y_axis: any;
private x_axis: any;
private svg: any;
private g: any;
private chart: any;
private tooltip: any;
private xAxis:any
private yAxis:any
private xScale:any
private yScale:any
private color:any
private resizeTimeout: any;
private qDomain = [500, 1000, 1500];
private qRange = ['blue', 'green', 'red']
@ViewChild('chartContainer')elementView: ElementRef;
@HostListener('window:resize')
onWindowResize() {
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
this.resizeTimeout = setTimeout((() => {
this.w = this.elementView.nativeElement.offsetWidth;
this.width = this.w - this.margin.left - this.margin.right;
this.initScales();
this.createAxis();
this.drawUpdate(this.data);
}).bind(this), 10);
}
constructor(private container: ElementRef) {}
ngOnInit() {
this.w = this.elementView.nativeElement.offsetWidth;
this.width = this.w - this.margin.left - this.margin.right;
this.initScales();
this.initSvg();
this.createAxis();
this.drawUpdate(this.data);
}
//----------------------- initScales
private initScales() {
this.x = d3.scaleBand()
.range([0, this.width])
.padding(.15)
this.y = d3.scaleLinear()
.rangeRound([this.height, 0]);
}
//----------------------- initSvg
private initSvg() {
this.svg = d3.select(this.container.nativeElement)
.select('.chart-container')
.append('svg')
this.chart = this.svg.append('g')
.attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")")
}
private createAxis(){
this.y_axis = d3.axisLeft(this.y)
.tickPadding(10)
.ticks(10)
this.x_axis = d3.axisBottom(this.x)
.scale(this.x)
.tickPadding(10);
this.chart.append("g").classed('y-axis', true);
this.chart.append("g").classed('x-axis', true);
}
//----------------------- drawUpdate
private drawUpdate(data){
this.x.domain(data.map( (d) => d.date) );
this.y.domain([0, d3.max( data, (d) => d.value) ]);
this.color = d3.scaleThreshold()
.domain([600, 800])
.range(['blue', 'green', 'red']);
const bar = this.chart.selectAll(".bar")
.data(data)
///Enter
bar.enter()
.append("rect")
.classed('bar', true)
.attr('x', (d) => this.x(d.date))
.attr("width", this.x.bandwidth())
.attr("y", (d) => this.y(d.value))
.attr("height", (d) => this.height - this.y(d.value))
.attr('fill', (d) => {
return this.color(d)
});
bar
.attr('x', (d) => this.x(d.date))
.attr("width", this.x.bandwidth())
.attr("y", (d) => this.y(d.value))
.attr("height", (d) => this.height - this.y(d.value))
.style('fill', (d) => {
return this.color(d)
})
bar.exit()
.remove()
d3.select('.y-axis')
.transition()
.call(this.y_axis)
.selectAll(".tick text")
d3.select('.x-axis')
.call(this.x_axis)
.attr("transform", "translate(0," + this.height + ")")
.selectAll(".tick text")
};
}
答案 0 :(得分:1)
在已经提供的两个注释(使用阈值量表;将d.values
传递到该量表)上,您对this
的含义有疑问。
在回调内部,this
是元素本身。所以,这:
.attr("fill", function(d){
return this.q_scale(d.value)
});
毫无意义,因为比例(q_scale
)不是元素的方法。
话虽如此,请使用箭头功能:
.attr("fill", (d) => this.q_scale(d.value));
或绑定其他this
:
.attr("fill", function(d){
return this.q_scale(d.value)
}.bind(this));
以下是您的代码所做的更改:https://stackblitz.com/edit/basic-bar-mt-zehzcv?file=src/app/bar-chart.ts