使用KiB,MiB,GiB单位设置d3轴,以字节为单位

时间:2017-10-05 21:53:39

标签: javascript d3.js

我有一个跟踪文件大小的图表。我想设置一个轴(Y),显示文件大小与适当的Mebibyte后缀ex:KiB,MiB,GiB等。

现在,我正在以字节为单位提供数据,因此从理论上讲,一个简单的.tickFormat()方法后面跟一个d3.format()就可以了。不幸的是情况并非如此,因为文件大小实际上是1024(或2 ^ 20)的倍数,而不是典型的SI 10 ^ 6。这意味着我的线开始绘制,但轴很奇怪。

以文件大小587108352为例,如果将其舍入到最接近的MB,则得到560MiB(使用1024(2 ^ 20)乘数)。

如何设置我的轴​​才能使用它?

我试过了:

yAxis = d3.axisLeft(y)
     .tickFormat(function (d) {
     return d3.format(scope.formatOptions.specifier)(d * scope.formatOptions.multiplier) + scope.formatOptions.suffix;
     });

格式选项对象是:

vm.FormatObjectSize = {
        specifier: ".0s", // decimal notation with an SI prefix, rounded to significant digits.
        multiplier: 1, // none
        suffix: "b" // bytes
    };

这不太合适:

enter image description here

1 个答案:

答案 0 :(得分:2)

您可以将tickFormat与函数一起使用来转换文件大小。在这里,我使用this answer中提供的函数,我将其命名为fileSize

因此,您的tickFormat应为:

.tickFormat(function(d){
    return fileSize(d)
 }

这是一个演示,从0587108352

var scale = d3.scaleLinear()
  .domain([0, 587108352])
  .range([20, 470]);

var svg = d3.select("svg");

var gX = svg.append("g").attr("transform", "translate(0,50)")
  .call(d3.axisBottom(scale).tickValues(scale.ticks(5).concat(scale.domain())).tickFormat(function(d) {
    return fileSize(d)
  }))

function fileSize(bytes) {
  var thresh = 1024;
  if (Math.abs(bytes) < thresh) {
    return bytes + ' B';
  }
  var units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
  var u = -1;
  do {
    bytes /= thresh;
    ++u;
  } while (Math.abs(bytes) >= thresh && u < units.length - 1);
  return bytes.toFixed(1) + ' ' + units[u];
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>

如您所见,587108352的最后一个值是559.9 Mebibytes,这是正确的值。

顺便说一句,你问题的标题有点不正确:你想要的实际上是 KiB,MiB,GiB 等,而不是Kb,Mb,Gb ......

此外,可以使用MB / GB / TB / etc或MiB / GiB / TiB /等提供文件/存储大小,具体取决于具体情况。例如,HD制造商通常使用十进制(1000),而RAM制造商通常使用1024。