var w = 500,
h = 220,
marginLeft = 30,
marginBottom = 30;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var data = [{
name: "foo",
value: 800
}, {
name: "bar",
value: 720
}, {
name: "baz",
value: 10
}, {
name: "foobar",
value: 17
}, {
name: "foobaz",
value: 840
}];
var xScale = d3.scaleBand()
.domain(data.map(function(d) {
return d.name
}))
.range([marginLeft, w])
.padding(.5);
var yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.value
})])
.range([h - marginBottom, 0]);
var bars = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.attr("x", function(d) {
return xScale(d.name)
})
.attr("width", xScale.bandwidth())
.attr("y", function(d) {
return yScale(d.value)
})
.attr("height", function(d) {
return h - marginBottom - yScale(d.value)
})
.style("fill", "teal");
var xAxis = d3.axisBottom(xScale)(svg.append("g").attr("transform", "translate(0," + (h - marginBottom) + ")"));
var yAxis = d3.axisLeft(yScale)(svg.append("g").attr("transform", "translate(" + marginLeft + ",0)"));
<script src="https://d3js.org/d3.v4.js"></script>
baz
和foobar
条形图因它们之间的差异非常大而被其他条形图所掩盖。var yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.value
})])
.range([h - marginBottom, 0]);
var yScale = d3.scaleLinear()
.domain([0, 20, 700, d3.max(data, function(d) {
return d.value
})])
.range([h - marginBottom, h/2 + 2, h/2 - 2, 0]);
如您所见,这里有一些魔法数字。根据您的需求进行更改。
通过插入中点,这是域和范围之间的相关性:
+--------+-------------+---------------+---------------+------------+
| | First value | Second value | Third value | Last value |
+--------+-------------+---------------+---------------+------------+
| Domain | 0 | 20 | 700 | 840 |
| | maps to... | maps to... | maps to... | maps to... |
| Range | height | heigh / 2 - 2 | heigh / 2 + 2 | 0 |
+--------+-------------+---------------+---------------+------------+
你可以看到相关性不是成比例的,这正是我们想要的。
这就是结果:
var w = 500,
h = 220,
marginLeft = 30,
marginBottom = 30;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var data = [{
name: "foo",
value: 800
}, {
name: "bar",
value: 720
}, {
name: "baz",
value: 10
}, {
name: "foobar",
value: 17
}, {
name: "foobaz",
value: 840
}];
var xScale = d3.scaleBand()
.domain(data.map(function(d) {
return d.name
}))
.range([marginLeft, w])
.padding(.5);
var yScale = d3.scaleLinear()
.domain([0, 20, 700, d3.max(data, function(d) {
return d.value
})])
.range([h - marginBottom, h/2 + 2, h/2 - 2, 0]);
var bars = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.attr("x", function(d) {
return xScale(d.name)
})
.attr("width", xScale.bandwidth())
.attr("y", function(d) {
return yScale(d.value)
})
.attr("height", function(d) {
return h - marginBottom - yScale(d.value)
})
.style("fill", "teal");
var xAxis = d3.axisBottom(xScale)(svg.append("g").attr("transform", "translate(0," + (h - marginBottom) + ")"));
var yAxis = d3.axisLeft(yScale).tickValues([0, 5, 10, 15, 700, 750, 800])(svg.append("g").attr("transform", "translate(" + marginLeft + ",0)"));
svg.append("rect")
.attr("x", marginLeft - 10)
.attr("y", yScale(19.5))
.attr("height", 10)
.attr("width", 20);
svg.append("rect")
.attr("x", marginLeft - 10)
.attr("y", yScale(19))
.attr("height", 6)
.attr("width", 20)
.style("fill", "white");
<script src="https://d3js.org/d3.v4.js"></script>
如您所见,我必须使用tickValues
设置y轴刻度,否则会很混乱。
最后,我再次强调:不要忘记显示y轴已经被打断。在上面的代码段中,我将符号(请参阅我的答案中的第一个图)放置在y轴上数字15
和数字700
之间。顺便说一句,值得注意的是,在您分享的图中,其作者没有在y轴上放置任何符号,这是不好的做法。