簡體   English   中英

如何在D3折線圖上擬合可變長度刻度標簽?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM