这是原始示例:https://bl.ocks.org/mbostock/7555321。
我在x轴上添加了过渡,并做了两个小提琴,以证明在过渡上将长标签包裹在轴上的事实在版本3中有效,但在D3的版本4中无效。
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.transition()
.call(xAxis)
.selectAll(".tick text")
// .call(wrap, x.rangeBand()); (v3)
.call(wrap, x.bandwidth());
https://jsfiddle.net/cfwbh0st/
https://jsfiddle.net/Ls5ux9gv/
我该如何处理?谢谢。
答案 0 :(得分:0)
当我发现问题的根本原因时,我正在重写您的逻辑。通过调用.transition()
,可以将对象从选择内容更改为过渡对象。但是过渡对象don't have a .html()
method。您没有意识到这一点,因为您使用了.call()
。但是,该操作在过渡完成之前 执行,因此,滴答声将被默认行为覆盖。我将在下面提出两个解决方案。第一个是您的代码的改编版,第二个是我正在处理的代码。希望它将为您提供更多的指导。
尽可能接近您的代码
var margin = {top: 80, right: 180, bottom: 80, left: 180},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(.1)
.paddingOuter(.3);
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom()
.scale(x);
var yAxis = d3.axisLeft()
.scale(y)
.ticks(8, "%");
var svg = d3.select("body").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 + ")");
d3.tsv("https://gist.githubusercontent.com/mbostock/7555321/raw/1b17baa35f75336a8d9f4c8292b1d1ab850f3d86/data.tsv", type, function(error, data) {
x.domain(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
svg.append("text")
.attr("class", "title")
.attr("x", x(data[0].name))
.attr("y", -26)
.text("Why Are We Leaving Facebook?");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.transition()
.call(xAxis)
.on("end", function() {
d3.select(this)
.selectAll(".tick text")
.call(wrap, x.bandwidth())
});
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.name); })
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
});
function wrap(textElements, width) {
textElements.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
function type(d) {
d.value = +d.value;
return d;
}
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.title {
font: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
var margin = {
top: 80,
right: 180,
bottom: 80,
left: 180
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(.1)
.paddingOuter(.3);
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom()
.scale(x);
var yAxis = d3.axisLeft()
.scale(y)
.ticks(8, "%");
var svg = d3.select("body").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 + ")");
d3.tsv("https://gist.githubusercontent.com/mbostock/7555321/raw/1b17baa35f75336a8d9f4c8292b1d1ab850f3d86/data.tsv", type, function(error, data) {
x.domain(data.map(function(d) {
return d.name;
}));
y.domain([0, d3.max(data, function(d) {
return d.value;
})]);
svg.append("text")
.attr("class", "title")
.attr("x", x(data[0].name))
.attr("y", -26)
.text("Why Are We Leaving Facebook?");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.transition()
.call(xAxis)
.on("end", function() {
d3.select(this).selectAll(".tick text")
.call(wrap, x.bandwidth())
});
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.name);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
});
});
function wrap(textElements, width) {
textElements.each(function() {
d3.select(this).html(function(text) {
var words = text.split(/\s+/),
word,
lines = [],
currentLine = '',
lineNumber = 0,
lineHeight = 1.1
while (word = words.shift()) {
if (getTextWidth(currentLine + word, "10px sans-serif") < width) {
// We're safe to add the word
currentLine += word + ' ';
} else {
// If we add the word, we exceed the line length
// Trim to remove the last space
lines.push('<tspan x="0" y="9" dy="' + (++lineNumber * lineHeight) + 'em">' + currentLine.trim() + '</tspan>')
currentLine = word + ' ';
}
}
lines.push('<tspan x="0" y="9" dy="' + (++lineNumber * lineHeight) + 'em">' + currentLine.trim() + '</tspan>')
return lines.join('');
});
});
}
/**
* Measure the width of a text were it to be rendered using a given font.
*
* @param {string} text the text to be measured
* @param {string} font a valid css font value
*
* @returns {number} the width of the rendered text in pixels.
*/
function getTextWidth(text, font) {
const element = document.createElement("canvas");
const context = element.getContext("2d");
context.font = font;
return context.measureText(text).width;
};
function type(d) {
d.value = +d.value;
return d;
}
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.title {
font: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>