我有一个高度为270像素的d3条形图。图表渲染得很好,但它超出了x轴标签。
当我尝试调整条形的y
或height
属性时,它们会覆盖svg
的边界,在最顶层(调整height
)或最底部(调整y
)。如何给条形图一个底部“边距”,以容纳标签?
构建图表的功能:
buildTimeline: ->
width = @ui.chartWrap.width()
height = @ui.chartWrap.height()
console.log height
dataLength = @data.values.length
x = d3.time.scale()
.domain(
[
new Date "#{@data.values[0].x}-1-1"
new Date("#{@data.values[dataLength - 1].x}-1-1")
]
).rangeRound [0, width - (width/dataLength - 1)]
y = d3.scale.linear()
.domain(
[
0
d3.max(@data.values, (d) ->
d.y
)
]
).rangeRound [height, 0]
xAxis = d3.svg.axis()
.scale(x)
.orient('bottom')
.ticks(d3.time.years, 1)
.tickFormat(d3.time.format('%Y'))
yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.tickPadding(8)
svg = d3.select(@ui.chartWrap[0]).append('svg')
.attr('width', width)
.attr('height', height)
# Bars
svg.append('g')
.attr('id', 'timeline-bars')
.selectAll(".bar")
.data(@data.values)
.enter().append("rect")
.attr("class", "bar")
.attr("x", (d) ->
x(new Date "#{d.x}-1-1")
)
.attr("width", width/dataLength - 1)
.attr("y", (d) ->
y(d.y)
)
.attr("height", (d) =>
height - y(d.y)
).attr("data-date", (d) =>
d.x
).attr("data-count", (d) =>
d.y
)
svg.append("g")
.attr('id', 'timeline-x-labels')
.call(xAxis)
图表的CSS(SASS):
#timeline
height: 270px
margin: 10px
cursor: crosshair
font-size: 1em
.bar
fill: blue
shape-rendering: crispEdges
&:hover
cursor: pointer
fill: darken(blue, 10)
#timeline-x-labels
+translate(0, 240px)
path, line
fill: none
stroke: shade(gainsboro, 10%)
shape-rendering: crispEdges
.tick > text
font-size: 0.7em
+user-select(none)
+transform(translate(0px, 10px) rotate(-60deg))
答案 0 :(得分:0)
尝试更改刻度上的范围,而不是调整图表的“x”和“y”属性。如果您使用.range(50, width)
(或.rangeround(50, width)
)而不是(0,width)
绘制比例,您将有效地为自己提供50px的保证金。
答案 1 :(得分:0)
我最终根据这里的教程重写了整个代码:http://bost.ocks.org/mike/bar/3/
最终产品如下所示:
buildTimeline: ->
margin =
top: 10
bottom: 30
left: 40
right: 10
width = @ui.chartWrap.width() - margin.left - margin.right
height = @ui.chartWrap.height() - margin.top - margin.bottom
dataLength = @data.values.length
y = d3.scale.linear()
.range([height, 0])
x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.1)
xAxis = d3.svg.axis()
.scale(x)
.orient 'bottom'
yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.tickFormat (d) ->
prefix = d3.formatPrefix d
prefix.scale(d) + prefix.symbol
@chart = d3.select(@ui.chartWrap[0]).append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g').attr('transform', "translate(#{margin.left}, #{margin.top})")
x.domain _.pluck(@data.values, 'x')
y.domain [0, d3.max(_.pluck(@data.values, 'y'))]
@chart.append('g')
.attr('id', 'timeline-x-axis')
.attr('class', 'axis')
.attr('transform', "translate(0, #{height})")
.call xAxis
@chart.append('g')
.attr('class', 'axis')
.call yAxis
@chart.selectAll('.bar')
.data(@data.values)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', (d) ->
x(d.x)
)
.attr('y', (d) ->
y(d.y)
)
.attr('height', (d) ->
height - y(d.y)
)
.attr('width', x.rangeBand())