in code/bias-variance/js/ErrorBar.js [501:641]
positionErrorBarsAsLabels() {
const that = this;
const nodeWidth = (d) => d.getBBox().width;
// const rectOffset = window.innerWidth <= 600 ? 4 : 8;
const rectOffsetX = window.innerWidth <= 600 ? 4 : 8;
const rectOffsetY = window.innerWidth <= 600 ? 4 : 8;
const symbolSpace =
window.innerWidth <= 600 ? rectOffsetX * 1.5 : rectOffsetX * 2;
const errorTransTime = 800;
// update y-axis
this.yScale.domain(["Test"]);
// hide label rects behind main rect
selectAll("rect.stacked").style("opacity", 0.7);
selectAll(".decomp-text").style("opacity", 1);
// position label rects
selectAll("rect.stacked")
.transition()
.attr("x", (d) => this.textBox[d.error].x - rectOffsetX)
.attr("y", (d) => this.textBox[d.error].y - rectOffsetY)
.attr("width", (d) =>
window.innerWidth <= 600
? this.textBox[d.error].width + 1.5 * rectOffsetX
: this.textBox[d.error].width + 2 * rectOffsetX
)
.attr("height", (d) => this.textBox[d.error].height + 2 * rectOffsetY);
let offset = 0;
this.decompGs
.transition()
.duration(errorTransTime)
.attr("transform", function (d) {
// resolve x position for transition
let x = offset;
offset += that.textBox[d.error].width + 2.5 * rectOffsetX + symbolSpace;
let currentxPos = that.decompAxis(d.error) - rectOffsetX * 2;
let xPos = that.WIDTH / 10 - currentxPos;
xPos += x;
xPos = window.innerWidth <= 600 ? xPos - that.MARGIN.LEFT / 2.5 : xPos;
// resolve y position for transition
let currentYPos = that.yScale.bandwidth() / 2 + that.MARGIN.TOP;
// that.yScale.bandwidth() / 2 + this.MARGIN.TOP
const yPos = -currentYPos;
// transition
return `translate(${xPos}, ${yPos})`;
})
.selectAll(".decomp-text")
.attr("text-anchor", "right");
this.decompLegend.attr("transform", function () {
return `translate(${(that.WIDTH - nodeWidth(this)) / 2}, 0)`;
});
// init error legend text to get position/bbox
let errorText = this.decompLegend
.append("text")
.attr("id", "error-text")
.attr("x", this.biasX)
.attr("y", this.MARGIN.TOP)
.text("Error")
.style("font-family", "AmazonEmberDisplayHeavy")
.style("opacity", 0);
// get bbox balues of text
let errorCoords = {};
select("#error-text").each(function (d, i) {
const textBox = this.getBBox();
const width = textBox.width + 2 * rectOffsetX;
const height = textBox.height + 2 * rectOffsetY;
errorCoords["x"] = that.biasX - width;
errorCoords["width"] = width;
errorCoords["height"] = height;
errorCoords["y"] = textBox.y;
});
// translate text to correct position given other elements and bbox
errorText
.transition()
.attr(
"x",
window.innerWidth <= 600
? errorCoords.x - rectOffsetX - that.MARGIN.LEFT / 2.5
: errorCoords.x - rectOffsetX
)
.attr("y", 0);
// add background rectangle
const errorTextRect = this.decompLegend
.append("rect")
.attr("class", "stacked-error")
.attr("fill", "red")
.attr(
"x",
window.innerWidth <= 600
? errorCoords.x - 2 * rectOffsetX - that.MARGIN.LEFT / 2.5
: errorCoords.x - 2 * rectOffsetX
)
.attr("y", errorCoords.y - rectOffsetY - that.MARGIN.TOP)
.attr("width", errorCoords.width)
.attr("height", errorCoords.height)
.lower()
.style("opacity", 0);
// ADD MATH SYMBOLS TO LEGEND
// add '=' sign after error
let errorTextEquals = this.decompLegend
.append("text")
.attr("class", "error-symbol")
.attr(
"x",
window.innerWidth <= 600
? errorCoords.x +
errorCoords.width -
rectOffsetX -
that.MARGIN.LEFT / 2.5
: errorCoords.x + errorCoords.width - rectOffsetX
)
.attr("y", 0)
.text("=")
.style("font-family", "AmazonEmberDisplayHeavy")
.style("opacity", 0);
// add '+' signs
let errorTextPlus = this.decompGs
.filter((d, i) => i !== 0)
.append("text")
.attr("class", "error-symbol")
.attr("x", (d) => this.textBox[d.error].x - rectOffsetX - symbolSpace)
.attr("dx", window.innerWidth <= 600 ? -2 : 0)
.attr("y", that.yScale.bandwidth() / 2 + this.MARGIN.TOP)
.text("+")
.style("font-family", "AmazonEmberDisplayHeavy")
.style("opacity", 0);
// transition elements to visibility
const errorTextT = transition().delay(errorTransTime);
errorText.transition(errorTextT).style("opacity", 1);
selectAll(".error-symbol").transition(errorTextT).style("opacity", 0.9);
errorTextRect.transition(errorTextT).style("opacity", 0.7);
}