我试图打破 y 轴标签的长线。我的条形图就像 this但标签较长(通常超过 10 个带有空格的单词)。这是我的代码(它有效,我看到了图表,唯一的“错误”是文本,我动态加载 JSON,此数据仅适用于 SO):
HTML:
<svg id='table1'></svg>
<script>
var window_width = $(window).width();
var main_width = (window_width / 100 ) * 80;
var w = main_width - 400;
var data = {
labels: [
'the text to be splitted 1', 'the text to be splitted 2'
],
series: [
{
label: '2012',
values: [4, 8]
},
{
label: '2013',
values: [12, 43]
}
]
};
var chartWidth = w,
barHeight = 25,
groupHeight = barHeight * data.series.length,
gapBetweenGroups = 10,
spaceForLabels = 175,
spaceForLegend = 0;
// Zip the series data together (first values, second values, etc.)
var zippedData = [];
for (var i=0; i<data.labels.length; i++) {
for (var j=0; j<data.series.length; j++) {
zippedData.push(data.series[j].values[i]);
}
}
var chartHeight = barHeight * zippedData.length + gapBetweenGroups * data.labels.length;
var x = d3.scale.linear()
.domain([0, d3.max(zippedData)])
.range([0, chartWidth]);
var y = d3.scale.linear()
.range([chartHeight + gapBetweenGroups, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat('')
.tickSize(0)
.orient("left");
// Specify the chart area and dimensions
var chart = d3.select("#table"+ambit)
.attr("width", spaceForLabels + chartWidth + spaceForLegend)
.attr("height", chartHeight);
// Create bars
var bar = chart.selectAll("g")
.data(zippedData)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + spaceForLabels + "," + (i * barHeight + gapBetweenGroups * (0.5 + Math.floor(i/data.series.length))) + ")";
});
// Create rectangles of the correct width
bar.append("rect")
.attr("fill", function(d,i) { return color(i % data.series.length); })
.attr("class", "bar")
.attr("width", x)
.attr("height", barHeight - 1);
// Add text label in bar
bar.append("text")
.attr("class", "label_txt1")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
// Draw labels
bar.append("text")
.attr("class", "label_txt")
.attr("x", function(d) { return - 10; })
.attr("y", groupHeight / 2)
.attr("dy", ".35em")
.text(function(d,i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i/data.series.length)];
else
return ""});
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + spaceForLabels + ", " + -gapBetweenGroups/2 + ")")
.call(yAxis);
</script>
我遵循多个示例来解决此问题,例如: How do I include newlines in labels in D3 charts? 和 Adding a line break to D3 graph y-axis labels和 Wrapping Long Labels .
第一次尝试:
var insertLinebreaks = function (d) {
var el = d3.select(this);
var words = d.split(' ');
el.text('');
for (var i = 0; i < words.length; i++) {
var tspan = el.append('tspan').text(words[i]);
if (i > 0)
tspan.attr('x', 0).attr('dy', '15');
}
};
chart.selectAll('g.y.axis text').each(insertLinebreaks);
和:
bar.selectAll('.label_txt1').each(insertLinebreaks);
我也尝试过:
bar.append("text")
.attr("class", "label_txt1")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
chart.selectAll(".label_txt1").call(wrap, 40)
function wrap(text, width) {
alert(JSON.stringify(text));
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
lineHeight = 1.1, // ems
tspan = text.text(null).append("tspan").attr("x", function(d) { return d.children || d._children ? -10 : 10; }).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
var textWidth = tspan.node().getComputedTextLength();
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
++lineNumber;
tspan = text.append("tspan").attr("x", function(d) { return d.children || d._children ? -10 : 10; }).attr("y", 0).attr("dy", lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
我改变了text()
至html()
正如我读到的:How do I include newlines in labels in D3 charts?
在浏览器中我看到 <text>
使用类 label_txt1
创建。当我尝试使用 selectAll(".label_txt1")
选择文本时我得到的是行的值,而不是文本。
有人可以帮助我吗?
最佳答案
这个example您引用的是使用 svg 文本节点时进行换行的规范方法。您只是将其称为错误的(在错误的类上,您正在包装数字)。将其简化为:
// Draw labels
bar.append("text")
.attr("class", "label_txt")
.attr("x", function(d) {
return -10;
})
.attr("y", groupHeight / 2) //<-- not sure you need this
.attr("dy", ".35em")
.text(function(d, i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i / data.series.length)];
else
return ""
})
.call(wrap, 40);
<小时/>
完整代码:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<svg id="table1"></svg>
<script>
var window_width = 1000;
var main_width = 400;
var w = 400;
var data = {
labels: [
'the text to be splitted 1', 'the text to be splitted 2'
],
series: [{
label: '2012',
values: [4, 8]
}, {
label: '2013',
values: [12, 43]
}]
};
var chartWidth = w,
barHeight = 25,
groupHeight = barHeight * data.series.length,
gapBetweenGroups = 10,
spaceForLabels = 175,
spaceForLegend = 0;
var color = d3.scale.category10();
// Zip the series data together (first values, second values, etc.)
var zippedData = [];
for (var i = 0; i < data.labels.length; i++) {
for (var j = 0; j < data.series.length; j++) {
zippedData.push(data.series[j].values[i]);
}
}
var chartHeight = barHeight * zippedData.length + gapBetweenGroups * data.labels.length;
var x = d3.scale.linear()
.domain([0, d3.max(zippedData)])
.range([0, chartWidth]);
var y = d3.scale.linear()
.range([chartHeight + gapBetweenGroups, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat('')
.tickSize(0)
.orient("left");
// Specify the chart area and dimensions
var chart = d3.select("#table1")
.attr("width", spaceForLabels + chartWidth + spaceForLegend)
.attr("height", chartHeight);
// Create bars
var bar = chart.selectAll("g")
.data(zippedData)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + spaceForLabels + "," + (i * barHeight + gapBetweenGroups * (0.5 + Math.floor(i / data.series.length))) + ")";
});
// Create rectangles of the correct width
bar.append("rect")
.attr("fill", function(d, i) {
return color(i % data.series.length);
})
.attr("class", "bar")
.attr("width", x)
.attr("height", barHeight - 1);
// Add text label in bar
bar.append("text")
.attr("class", "label_txt1")
.attr("x", function(d) {
return x(d) - 3;
})
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) {
return d;
});
// Draw labels
bar.append("text")
.attr("class", "label_txt")
.attr("x", function(d) {
return -10;
})
//.attr("y", groupHeight / 2) //<-- you don't need this...
.attr("dy", ".35em")
.text(function(d, i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i / data.series.length)];
else
return ""
})
.call(wrap, 40);
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
lineHeight = 1.1, // ems
tspan = text.text(null).append("tspan").attr("x", function(d) {
return d.children || d._children ? -10 : 10;
}).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
var textWidth = tspan.node().getComputedTextLength();
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
++lineNumber;
tspan = text.append("tspan").attr("x", function(d) {
return d.children || d._children ? -10 : 10;
}).attr("y", 0).attr("dy", lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + spaceForLabels + ", " + -gapBetweenGroups / 2 + ")")
.call(yAxis);
</script>
</body>
</html>
关于javascript - D3垂直条形图为标签文本添加换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36066183/