-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
capacity.tsx
118 lines (91 loc) · 2.5 KB
/
capacity.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import d3 from "d3";
import React from "react";
import { ComputeByteScale } from "src/util/format";
const size = {
width: 250,
height: 20,
};
const margin = {
top: 12,
right: 35,
bottom: 25,
left: 20,
};
const TICK_SIZE = 6;
const AXIS_MARGIN = 4;
interface CapacityChartProps {
used: number;
usable: number;
}
const scale = d3.scale.linear()
.range([0, size.width]);
const axis = d3.svg.axis()
.scale(scale)
.tickSize(TICK_SIZE)
.ticks(5);
function recomputeScale(el: d3.Selection<CapacityChartProps>) {
const capacity = el.datum();
// Compute the appropriate scale factor for a value slightly smaller than the
// usable capacity, so that if the usable capacity is exactly 1 {MiB,GiB,etc}
// we show the scale in the next-smaller unit.
const byteScale = ComputeByteScale(capacity.usable - 1);
const scaled = {
used: capacity.used / byteScale.value,
usable: capacity.usable / byteScale.value,
};
el.datum(scaled);
axis.tickFormat(function (d) {
return d + " " + byteScale.units;
});
scale.domain([0, scaled.usable]);
}
function chart(el: d3.Selection<CapacityChartProps>) {
el.style("shape-rendering", "crispEdges");
recomputeScale(el);
const axisGroup = el.selectAll("g.axis")
.data(() => [0]);
axisGroup.enter()
.append("g")
.attr("class", "axis")
.attr("transform", `translate(0,${size.height + AXIS_MARGIN})`);
axisGroup.call(axis);
axisGroup.selectAll("text").attr("y", AXIS_MARGIN + TICK_SIZE);
const bg = el.selectAll(".bg")
.data((d: CapacityChartProps) => [d]);
bg.enter()
.append("rect")
.attr("class", "bg");
bg
.attr("width", size.width)
.attr("height", size.height);
const bar = el.selectAll(".bar")
.data((d: CapacityChartProps) => [d]);
bar.enter()
.append("rect")
.attr("class", "bar")
.attr("height", 10)
.attr("y", 5);
bar
.attr("width", (d: CapacityChartProps) => scale(d.used));
}
export class CapacityChart extends React.Component<CapacityChartProps, {}> {
svgEl: SVGElement;
componentDidMount() {
d3.select(this.svgEl)
.datum(this.props)
.call(chart);
}
shouldComponentUpdate(props: CapacityChartProps) {
d3.select(this.svgEl)
.datum(props)
.call(chart);
}
render() {
return (
<svg width={size.width + margin.left + margin.right} height={size.height + margin.top + margin.bottom}>
<g ref={(el) => this.svgEl = el} transform={`translate(${margin.left},${margin.top})`}>
</g>
</svg>
);
}
}