首先,我们很想使用一个简单的解决方案,它依赖于轴生成器为每个刻度创建一个这样的结构(不要介意值,只是结构):
<g class="tick" opacity="1" transform="translate(66.5,0)">
<line stroke="#000" y2="6">
</line><text fill="#000" y="9" dy="0.71em">10</text>
</g>
所以,我们可以使用<lines> 和getBoundingClientRect() 来附加我们的矩形。为此,我们将在轴组中使用each()。
第一步如果检查tick是否有下一个tick,因为在最后一个tick之后不会有矩形:
if (this.nextSibling) {
然后,我们使用这个数学来附加矩形:
d3.select(this).append("rect")
.attr("width", this.nextSibling.firstChild.getBoundingClientRect().x -
this.firstChild.getBoundingClientRect().x)
.attr("height", 6)
.style("fill", i % 2 ? "green" : "red");
在此示例中,我使用刻度的索引来绘制“绿色”或“红色”矩形。注意:那个幻数6 只是 D3 中刻度的默认高度。相应地改变它。
这里是演示:
var svg = d3.select("svg");
var scale = d3.scaleLinear()
.domain([0, 100])
.range([20, 480]);
var axis = d3.axisBottom(scale);
var gX = svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0,50)")
.call(axis);
gX.selectAll(".tick").each(function(d, i) {
if (this.nextSibling) {
d3.select(this).append("rect")
.attr("width", this.nextSibling.firstChild.getBoundingClientRect().x - this.firstChild.getBoundingClientRect().x)
.attr("height", 6)
.style("fill", i % 2 ? "green" : "red");
}
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
但是,在您的情况下,这是行不通的。为什么?
根据您的图像,您的问题是第一个和最后一个滴答声。这是解释:那些不是蜱虫。这些“线”属于在轴中创建水平线的路径。
如果我们稍微改变一下域,我们可以清楚地看到这一点,看看:
var svg = d3.select("svg");
var scale = d3.scaleLinear()
.domain([5, 105])
.range([20, 480]);
var axis = d3.axisBottom(scale);
var gX = svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0,50)")
.call(axis);
gX.selectAll(".tick").each(function(d, i) {
if (this.nextSibling) {
d3.select(this).append("rect")
.attr("width", this.nextSibling.firstChild.getBoundingClientRect().x - this.firstChild.getBoundingClientRect().x)
.attr("height", 6)
.style("fill", i % 2 ? "green" : "red");
}
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
那么,如何处理呢?
解决方案:将那些“假”刻度转换为“真实”厚度。这可以使用tickValues:
.tickValues(scale.ticks().concat(scale.domain()));
作为一个额外的复杂功能,我们必须在此之后对刻度进行排序:
gX.selectAll(".tick").sort(function(a, b) {
return d3.ascending(a, b);
});
这里是演示:
var svg = d3.select("svg");
var scale = d3.scaleLinear()
.domain([5, 105])
.range([20, 480]);
var axis = d3.axisBottom(scale)
.tickValues(scale.ticks().concat(scale.domain()))
.tickFormat(function(d,i,n){
return i === n.length - 1 || i === n.length - 2 ? null : d;
});
var gX = svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0,50)")
.call(axis);
gX.selectAll(".tick").sort(function(a, b) {
return d3.ascending(a, b);
});
gX.selectAll(".tick").each(function(d, i) {
if (this.nextSibling) {
d3.select(this).append("rect")
.attr("width", this.nextSibling.firstChild.getBoundingClientRect().x - this.firstChild.getBoundingClientRect().x)
.attr("height", 6)
.style("fill", i % 2 ? "green" : "red");
}
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>