我有以下条形图。
https://jsfiddle.net/zyjp1abo/
正如您所看到的,值介于1000和1005之间。显示0到1005之间的所有数据都没有意义,因为差异不可见。
我想显示1000和1005之间的条形并相应地更改y轴。简单地使用extent
并更改域不起作用,因为条形图是通过底部边距绘制的。我希望它们停在最低值,即1000。
https://jsfiddle.net/zyjp1abo/1/
有什么想法吗?谢谢!
答案 0 :(得分:1)
更改域名后,此行:
.attr('height', d => Math.abs(y(d.value) - y(0)))
仍在根据0
值计算条形的高度。在this example中计算高度的传统方法是将其基于图表的内部高度(变量h
)。
这是一个更新的fiddle。
答案 1 :(得分:1)
如果您希望域名从1000转到1005,则应使用d3.extent
。那不是问题。
问题在于您使用的是d3.extent
,但是您继续使用y(0)
来翻译x轴和计算条形高度,这是错误的。您必须使用height
和您的边距。
以下是包含这些更改的代码:
var defaults = {
target: '#chart',
width: 500,
height: 170,
margin: {
top: 20,
right: 20,
bottom: 20,
left: 50
},
yTicks: 5
}
class Barchart {
constructor(config) {
Object.assign(this, defaults, config)
const {
target,
width,
height,
margin
} = this
const w = width - margin.left - margin.right
const h = height - margin.top - margin.bottom
const {
yTicks
} = this
this.chart = d3.select(target)
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
this.x = d3.scaleBand()
.rangeRound([0, w])
.padding(0.1)
this.y = d3.scaleLinear()
.rangeRound([h, 0])
this.xAxis = d3.axisBottom(this.x)
this.chart.append('g')
.attr('class', 'x axis')
this.yAxis = d3.axisLeft(this.y)
.ticks(yTicks)
this.chart.append('g')
.attr('class', 'y axis')
}
render(data) {
const {
x,
y,
xAxis,
yAxis,
chart
} = this
// y.domain(d3.extent(data, v => v.value))
y.domain(d3.extent(data, v => v.value))
const domain = data.map(d => d.timestamp)
x.domain(domain)
chart.select('.x.axis')
.attr('transform', `translate(0, ${(defaults.height - defaults.margin.bottom - defaults.margin.top)})`)
.call(xAxis)
chart.select('.y.axis')
.call(yAxis)
const bars = chart.selectAll('.bar')
.data(data)
bars
.enter()
.append('rect')
.attr('class', 'bar')
.merge(bars)
.attr('x', d => x(d.timestamp))
.attr('y', d => y(d.value))
.attr('width', x.bandwidth())
.attr('height', d => defaults.height - defaults.margin.bottom - defaults.margin.top - y(d.value))
}
}
const random = (min = -10, max = 10) => (
window.Math.floor(window.Math.random() * (max - min + 1)) + min
)
let bar = []
for (let i = 0; i < 20; i++) {
bar.push({
timestamp: Date.now() - (19 - i) * 500,
value: random(1000, 1005)
})
}
const barchart = new Barchart()
barchart.render(bar)
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg id="chart">
</svg>
&#13;
PS:您可以简化SVG大小和边距的数学运算。
PPS:关于dataviz是否可以具有非零基线,存在很多争论。我相信,在某些情况下,当变化率比绝对值更重要时,某些类型的图表可以而且应该具有非零基线,特别是折线图。但是,条形图应始终的基线为零。
答案 2 :(得分:0)
y.domain([0, d3.max(data, v => v.value)])
将此处的0
更改为1000
,以及其他地方