[英]How to fit variable length tick labels on a D3 line chart?
這是一個JSFiddle: http : //jsfiddle.net/8p2yc/ (這里有一個稍微修改過的例子: http ://bl.ocks.org/mbostock/3883245)
正如您在JSFiddle中看到的那樣,沿y軸的刻度標簽不適合svg。 我知道我可以增加左邊距,但問題是我不知道預先提供了什么數據。 如果我只是使邊距非常大,如果數字很短,圖表看起來會很尷尬。
有沒有辦法在創建圖表時預先計算最大標簽寬度以正確設置邊距? 或許還有一個完全不同的解決方案?
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 400 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
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 + ")");
謝謝!
您可以通過附加最大標簽的文本,測量它並在之后立即將其刪除來完成此操作:
var maxLabel = d3.max(data, function(d) { return d.close; }),
maxWidth;
svg.append("text").text(maxLabel)
.each(function() { maxWidth = this.getBBox().width; })
.remove();
然后您可以使用該寬度來執行g
元素的轉換:
svg.attr("transform", "translate(" + Math.max(margin.left, maxWidth) + "," + margin.top + ")");
在這里完成示例。
編輯:獲取實際標簽的最大長度需要更多參與,因為您必須生成它們(使用正確的格式)並測量它們。 當你測量實際顯示的內容時,這是一種更好的方法。 代碼類似:
var maxWidth = 0;
svg.selectAll("text.foo").data(y.ticks())
.enter().append("text").text(function(d) { return y.tickFormat()(d); })
.each(function(d) {
maxWidth = Math.max(this.getBBox().width + yAxis.tickSize() + yAxis.tickPadding(), maxWidth);
})
.remove();
我在這里添加了刻度線的大小和刻度線和標簽之間的填充。 這里有完整的例子。
假設您希望軸和繪圖組合以填充固定空間,並且您的刻度標簽將自動生成,雞和蛋的問題可以防止這種情況被可靠地預先計算。
問題是刻度標簽以及它們所需的空間取決於規模。 例如,時間尺度可以包括在較短域上的較長月份名稱(例如“9月”),但是較短的月份名稱或僅在長域上的年份。 但是,至少在相反的軸上,比例取決於范圍的剩余空間,這取決於確定刻度標簽后留下的空間。
在很多情況下,最小值和最大值可以讓您了解最寬的刻度標簽,並且可以使用Lars的方法 。 例如,如果域為-50到10,則這些域之間的任何刻度標簽將更窄。 但這假設它們是整數! 另外,要注意' 漂亮 '的尺度; 如果你的最大值是8,D3可能會嘗試制作最大的刻度標簽10,這是一個更寬的字符串。
d3 v4 Lars方法的解決方案。
calculateMarginForYScaleTicks() {
let maxWidth = 0;
let textFormatter = d3.format(",");
let tempYScale = d3
.scaleLinear()
.range([0, 0])
.domain([0, d3.max(data, d => d.value)]);
d3
.select("#svg")
.selectAll("text.foo")
.data(tempYScale.ticks())
.enter()
.append("text")
.text(d => textFormatter(d))
.each(function() {
maxWidth = Math.max(this.getBBox().width, maxWidth);
})
.remove();
return maxWidth;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.