blob: ae539fdc10a567d4931d131b59fd39ef3df4f1eb [file] [log] [blame]
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
function Range(low, center, high, min, max, width, height, unit, higherIsBetter) {
const margin = 40;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");
const goodColor = "#005AB5";
const badColor = "#DC3220";
const pickColor = function(n) {
if (higherIsBetter) {
if (n > 0) {
return goodColor;
}
return badColor;
}
if (n < 0) {
return goodColor;
}
return badColor;
};
const xScale = d3.scaleLinear([min, max], [margin, width-margin]);
const yBaseline = 3*height/4;
// Draw zero line.
const tick = d3.line()
.x(d => xScale(d[0]))
.y(d => d[1])
svg.append("path")
.attr("fill", "none")
.attr("stroke", "#cccccc")
.attr("stroke-width", 1)
.attr("d", tick([[0, 0], [0, height]]))
// Draw line.
const line = d3.line()
.x(d => xScale(d))
.y(yBaseline)
const partialStroke = function() {
return svg.append("path")
.attr("fill", "none")
.attr("stroke-width", 3.5);
}
if (high < 0) {
partialStroke().attr("stroke", pickColor(high))
.attr("d", line([low, high]));
} else if (low < 0 && high > 0) {
partialStroke().attr("stroke", pickColor(low))
.attr("d", line([low, 0]));
partialStroke().attr("stroke", pickColor(high))
.attr("d", line([0, high]));
} else {
partialStroke().attr("stroke", pickColor(low))
.attr("d", line([low, high]));
}
const xTicks = [low, center, high];
for (const i in xTicks) {
svg.append("path")
.attr("fill", "none")
.attr("stroke", pickColor(xTicks[i]))
.attr("stroke-width", 2.5)
.attr("d", tick([[xTicks[i], yBaseline-4], [xTicks[i], yBaseline+4]]))
}
svg.append("text")
.attr("x", xScale(low)-4)
.attr("y", yBaseline+3)
.attr("fill", pickColor(low))
.attr("text-anchor", "end")
.attr("font-size", "11px")
.text(Intl.NumberFormat([], {
style: 'percent',
signDisplay: 'always',
minimumFractionDigits: 2,
}).format(low));
svg.append("text")
.attr("x", xScale(center))
.attr("y", height/2)
.attr("fill", pickColor(center))
.attr("text-anchor", "middle")
.attr("font-size", "16px")
.text(Intl.NumberFormat([], {
style: 'percent',
signDisplay: 'always',
minimumFractionDigits: 2,
}).format(center));
svg.append("text")
.attr("x", xScale(high)+4)
.attr("y", yBaseline+3)
.attr("fill", pickColor(high))
.attr("text-anchor", "start")
.attr("font-size", "11px")
.text(Intl.NumberFormat([], {
style: 'percent',
signDisplay: 'always',
minimumFractionDigits: 2,
}).format(high));
return svg.node();
}