我正在为D3做基本的条形图教程,但是yAxis的刻度并没有出现,即使该行也是如此。这个问题已经被问了很多,但我仍然没有找到适合我具体情况的答案。这是我的代码:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000000;
}
.x.axis path {
display: none;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<svg class="chart"></svg>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
<script src="https://d3js.org/d3-scale.v1.min.js"></script>
<script>
var data = [4, 8, 15, 16, 23, 42];
var width = 960, height = 500
var barWidth = width / data.length
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d)])
.range([height, 0])
var chart = d3.select(".chart")
.attr('width', width)
.attr('height', height)
chart.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
var groups = chart.selectAll(".bar")
.data(data)
.enter().append("g")
.attr('transform', (d, i) => `translate(${i * barWidth}, 0)`)
groups.append('rect')
.attr('y', (d) => yScale(d))
.attr('height', (d) => height - yScale(d))
.attr('width', barWidth - 1)
groups.append('text')
.attr('x', barWidth / 2)
.attr('height', (d) => height - yScale(d))
.attr('width', barWidth - 1)
.text(d => d)
</script>
有趣的事实:当我使用axisBottom而不是axisLeft附加轴时,我可以看到轴的刻度(显然没有正确定向)。感谢您的帮助!
答案 0 :(得分:1)
这里的问题是轴生成器创建了一个轴,当被调用(使用call
)时,在0,0
位置绘制:
无论方向如何,轴始终在原点处渲染。
所以,你需要translate
轴,向右移动一点:
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(30,0)")//magic number, change it at will
.call(d3.axisLeft(yScale));
以下是演示:
<style>
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000000;
}
.x.axis path {
display: none;
}
.chart rect {
fill: steelblue;
}
.barText {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<svg class="chart"></svg>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
<script src="https://d3js.org/d3-scale.v1.min.js"></script>
<script>
var data = [4, 8, 15, 16, 23, 42];
var width = 500, height = 300
var barWidth = width / data.length
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d)])
.range([height - 10, 0])
var chart = d3.select(".chart")
.attr('width', width)
.attr('height', height)
var groups = chart.selectAll(".bar")
.data(data)
.enter().append("g")
.attr('transform', (d, i) => `translate(${i * barWidth + 30}, 0)`)
groups.append('rect')
.attr('y', (d) => yScale(d))
.attr('height', (d) => height - 10 - yScale(d))
.attr('width', barWidth - 1)
groups.append('text')
.attr("class", "barText")
.attr('x', barWidth / 2)
.attr('y', d=> yScale(d) + 16)
.attr('height', (d) => height - 10 - yScale(d))
.attr('width', barWidth - 1)
.text(d => d)
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(30,0)")
.call(d3.axisLeft(yScale));
</script>
&#13;
PS:您的代码中还有一些其他问题,您可以改进(在这里,我只是回答您的问题):
bandwidth()
会自动完成。答案 1 :(得分:0)
我不是专家,但我想我已经明白了。你没有为你的.text()指定approriate x,y ...我修改了适合我的代码......看看JS小提琴:
https://jsfiddle.net/wpfkm6dn/2/
代码如下:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000000;
}
.x.axis path {
display: none;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<svg class="chart"></svg>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
<script src="https://d3js.org/d3-scale.v1.min.js"></script>
<script>
var data = [4, 8, 15, 16, 23, 42];
var width = 960, height = 500
var barWidth = width / data.length
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d)])
.range([height, 0])
var chart = d3.select(".chart")
.attr('width', width)
.attr('height', height)
chart.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
var groups = chart.selectAll(".bar")
.data(data)
.enter().append("g")
.attr('transform', (d, i) => `translate(${i * barWidth}, 0)`)
groups.append('rect')
.attr('y', (d) => yScale(d))
.attr('height', (d) => height - yScale(d))
.attr('width', barWidth - 1)
groups.append('text')
.attr('y', (d) => yScale(d) + 20)
.attr('x', barWidth / 2)
.attr('height', (d) => height - yScale(d))
.attr('width', barWidth - 1)
.text(d => d)
</script>
答案 2 :(得分:0)
不确定你是否已经解决了这个问题,但我采取了另一种方法。 fiddle
var data = [4, 8, 15, 16, 23, 42];
var svg = d3.select(".chart");
// we need to set a margin so that the yAxis has space to display
var margin = {top: 20, right: 20, bottom: 30, left: 40};
// these variables are assigned such that the margin is already deducted
var width = +svg.attr("width") - margin.left - margin.right;
var height = +svg.attr("height") - margin.top - margin.bottom;
var padding = 5; //5 px padding between bars
var barWidth = width / data.length - padding;
var yScale = d3.scaleLinear()
.domain([0, d3.max(data)]) // here we can just call d3.max(data) because data is an array
.range([height, 0]);
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
g.append('g')
.attr('class', 'axis axis--y')
.call(d3.axisLeft(yScale).ticks(5));
g.selectAll('.bar')
.data(data)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d, i) { return (barWidth + padding) * i; })
.attr('y', function(d) { return yScale(d); })
.attr('width', barWidth)
.attr('height', function(d) { return height - yScale(d); });