我想在条形图后面移动网格线,实际上我在upgradeChart()函数的条形图之前打印网格线,有什么建议吗? 我需要网格线:)我不能删除它们。 这是我的代码:
import { Component, OnInit, OnChanges, ViewChild, ElementRef, AfterViewInit, ViewEncapsulation, Input } from '@angular/core';
import * as d3 from 'd3';
import * as _d3Tip from 'd3-tip';
@Component({
selector: 'app-histogram',
templateUrl: './histogram.component.html',
styleUrls: ['./histogram.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class HistogramComponent implements OnInit, OnChanges {
@ViewChild('chart') private chartContainer: ElementRef;
@Input() public config;
private chart;
private margin;
private width;
private height;
private xScale;
private yScale;
private xAxis;
private yAxis;
private element;
private svg;
constructor() {
}
ngOnInit() {
console.log(this.config);
this.createChart( );
if (this.config.data) {
this.updateChart();
}
}
ngOnChanges() {
if (this.chart) {
this.updateChart();
}
}
public createChart() {
// Traemos el elemento donde estará el gráfico en este caso #chart
this.element = this.chartContainer.nativeElement;
// Guardamos los datos en una constante
const data = this.config.data;
// Declaramos el margen, el ancho y la altura del gráfico según los estilos del div #chart (d3-chart)
this.margin = { top: 40, right: 20, bottom: 30, left: 40 };
this.width = this.element.offsetWidth - this.margin.left - this.margin.right;
this.height = this.element.offsetHeight - this.margin.top - this.margin.bottom;
this.svg = d3.select(this.element).append('svg')
.attr('width', this.element.offsetWidth)
.attr('height', this.element.offsetHeight);
// chart plot area
this.chart = this.svg.append('g')
.attr('class', 'bars')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
// Creamos las escalas
this.xScale = d3.scaleBand().range([0, this.width]).padding(0.3);
this.yScale = d3.scaleLinear().range([this.height, 0]);
// Definimos la posicion del eje X en la parte de abajo
this.xAxis = this.svg.append('g')
.attr('class', 'x axis')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top + this.height})`)
.call(d3.axisBottom(this.xScale));
// Definimos la posicion del eje Y en la parte izquierda con su formato..
this.yAxis = this.svg.append('g')
.attr('class', 'y axis')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`)
.call(d3.axisLeft(this.yScale));
}
public updateChart() {
// Necesario al importar la libreria d3-tip para versiones superiores a 4 en d3.js
const d3Tip = _d3Tip.bind(d3);
// Creamos el tooltip
const tip = d3Tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return '<span class="highlight">' + d.valueY + '€' + '</span>';
});
this.svg.call(tip);
// Definimos los datos de las escalas
this.xScale.domain(this.config.data.map( d => d.valueX));
this.yScale.domain([0, d3.max(this.config.data, d => d.valueY)]);
this.xAxis.transition().call(d3.axisBottom(this.xScale));
this.yAxis.transition().call(d3.axisLeft(this.yScale).tickSize(-this.width).ticks(4).tickFormat(d => d + '€'));
const update = this.chart.selectAll('.bar')
.data(this.config.data);
// remove exiting bars
update.exit().remove();
// update existing bars
this.chart.selectAll('.bar').transition()
.attr('x', d => this.xScale(d.valueX))
.attr('y', d => this.yScale(d.valueY))
.attr('width', d => this.xScale.bandwidth())
.attr('height', d => this.height - this.yScale(d.valueY));
update
.enter().append('rect')
.attr('class', 'bar')
.attr('data-index', function(d, i) { return i; })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.attr('x', d => this.xScale(d.valueX))
.attr('y', d => this.yScale(d.valueY))
.attr('width', this.xScale.bandwidth())
.transition()
.ease(d3.easeLinear)
.duration(300)
.delay((d, i) => i * 50)
.attr('height', d => this.height - this.yScale(d.valueY));
}
}
问题在于这一行:
this.yAxis.transition().call(d3.axisLeft(this.yScale).tickSize(-this.width).ticks(4).tickFormat(d => d + '€'));
此行执行网格线:
.tickSize(-this.width).ticks(4).tickFormat(d => d + '€')
我从我的barChart中提取了一张照片 Bar Chart d3.js v5
网格解决方案:
解决方案是放置此代码:
// chart plot area
this.chart = this.svg.append('g')
.attr('class', 'bars')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`);
之后:
// Definimos la posicion del eje Y en la parte izquierda con su formato..
this.yAxis = this.svg.append('g')
.attr('class', 'y axis')
.attr('transform', `translate(${this.margin.left}, ${this.margin.top})`)
.call(d3.axisLeft(this.yScale));
编辑:另一个问题:
答案 0 :(得分:1)
我不确定没有小提琴但是,svg最初没有z-index。元素基于DOM树分层。最后绘制的内容显示在顶部。在你的情况下,我看到:
this.xAxis = this.svg.append('g')...
和
this.yAxis = this.svg.append('g')..
现在不是直接在svg上将它们作为g元素添加,而是尝试为两个轴创建包装g:
this.wrapper = this.svg.append('g');
然后代替上述2,执行:
this.xAxis = this.wrapper.append('g')...
确保在添加元素之前添加了包装器g元素。缓解问题的那个?
对于您的其他问题,
2 - 有多种方法可以使其响应,最简单的方法之一是在svg上使用preserveAspectRatio =“none”属性,然后使用css媒体查询控制div或包装svg的任何元素。如果你的意思是改变绘制轴等的方式,那么你必须调用一个更新函数来更新窗口"resize"
事件中的这些元素。
3 - 在图表上设置x,y或width高度或转换属性时使用Math.max和Math.min
.attr("height",function(d,i){return Math.min(someMin,someScale(d))})