以字节为单位使用 KiB、MiB、GiB 单位设置 d3 轴
Posted
技术标签:
【中文标题】以字节为单位使用 KiB、MiB、GiB 单位设置 d3 轴【英文标题】:setting up d3 axis with KiB, MiB, GiB units from values in bytes 【发布时间】:2017-10-05 21:53:39 【问题描述】:我有一个跟踪文件大小的图表。我想设置一个显示文件大小的轴 (Y),并带有适当的 Mebibyte 后缀,例如: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
;
这不太好用:
【问题讨论】:
Sugar.js 库有一种方法可以为您将数字概括为字符串:sugarjs.com/docs/#/Number/bytes 【参考方案1】:您可以将tickFormat
与转换文件大小的函数一起使用。在这里,我使用了this answer中提供的函数,我将其命名为fileSize
。
所以,你的tickFormat
应该是:
.tickFormat(function(d)
return fileSize(d)
这是一个演示,从0
到587108352
:
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 ></svg>
如您所见,587108352
的最后一个值是 559.9 Mebibytes,这是正确的值。
顺便说一句,你的问题的标题有点不正确:你想要的实际上是 KiB、MiB、GiB 等,而不是 Kb、Mb、Gb...
此外,文件/存储大小可以使用 MB/GB/TB/etc 或 MiB/GiB/TiB/etc 来提供,这取决于具体情况。例如,HD 厂商通常使用十进制(1000),而 RAM 厂商通常使用 1024。
【讨论】:
一如既往的惊人答案和很好的解释。谢谢!以上是关于以字节为单位使用 KiB、MiB、GiB 单位设置 d3 轴的主要内容,如果未能解决你的问题,请参考以下文章
以 MiB / GiB 为单位的 Ansible stat 模块目录大小输出。如何转换输出?