chart = {
let svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("background", "#1B1A40");
svg.append("style").text(`
.tranche--active {
text-decoration: underline
}
`);
var apyToggle = true;
var t = d3.transition().duration(1000);
const dataProps = [
{ line: "netAApy", bar: "trancheAValueUSD", sliceLine: "sliceAApy" },
{ line: "netBApy", bar: "trancheBValueUSD", sliceLine: "sliceBApy" }
];
let selectedData = dataProps[0];
let trancheToggle = true;
let hoveredIndex = -1;
let hoverGroup = svg
.append("g")
.attr("transform", `translate(0,${margin.bottom})`);
let hoverLine = hoverGroup
.append("line")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", 0)
.attr("y2", 0)
.attr("stroke-dasharray", "4,4")
.attr("stroke", "white")
.attr("stroke-width", 2)
.attr("class", "hover");
let dateText = svg
.append("text")
.attr("opacity", 0)
.attr("fill", "white")
.attr("font-size", 14)
.attr("text-anchor", "middle")
.text("gigi");
let rects = svg
.append("g")
.attr("fill", rectColor)
.attr("transform", `translate(0,${height - rectHeight - margin.bottom})`);
function updateRects() {
rects
.selectAll("rect")
.data(chartData[selectedData.bar])
.join("rect")
.attr("x", (d, i) => x(i))
.attr("class", (d, i) => `rect-${i} bar`)
.attr("width", x.bandwidth())
.transition()
.duration(2000)
.attr("y", (d) => y(d))
.attr("height", (d) => y(0) - y(d));
}
let hoverText = rects
.append("text")
.attr("opacity", 0)
.attr("class", "hover")
.attr("fill", "white")
.attr("text-anchor", "middle")
.text("");
let subtitleHoverText = rects
.append("text")
.attr("opacity", 0)
.attr("class", "hover")
.attr("fill", "white")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.text("TRANCHE VALUE");
let lineGroup = svg
.append("g")
.attr("class", "line-group")
.attr("transform", `translate(0,${rectHeight - 50})`);
var netALine = lineGroup
.append("path")
.attr("stroke", lineColor)
.attr("fill", "none")
.attr("stroke-width", 3)
.attr("opacity", 0.8);
var netBLine = lineGroup
.append("path")
.attr("stroke", lineColor)
.attr("fill", "none")
.attr("stroke-width", 3)
.attr("opacity", 0.2);
function updateLines() {
var aData = apyToggle
? chartData[dataProps[0]["line"]]
: chartData[dataProps[0]["sliceLine"]];
var bData = apyToggle
? chartData[dataProps[1]["line"]]
: chartData[dataProps[1]["sliceLine"]];
yLine.domain([0, d3.max([d3.max(aData), d3.max(bData)])]);
netALine.attr("d", line(aData));
netBLine.attr("d", line(bData));
var aLabel = "Tranche A";
var bLabel = "Tranche B";
netAApyLabel.text(aLabel);
netBApyLabel.text(bLabel);
}
var title = svg
.append("text")
.attr("fill", "white")
.attr("text-anchor", "start")
.attr("x", margin.left)
.attr("y", 40)
.attr("font-size", 22)
.attr("font-weight", 700)
.text("Tranche Performance");
const toggleWidth = 200;
var toggleHeight = 30;
var toggleGroup = svg
.append("g")
.attr("transform", `translate(250,${40 - toggleHeight + 5})`);
let toggleRect = toggleGroup
.append("rect")
.attr("x", margin.left)
.attr("y", 0)
.attr("width", toggleWidth)
.attr("height", toggleHeight)
.attr("fill", "#26254A")
.attr("rx", toggleHeight / 2)
.attr("ry", toggleHeight / 2);
let activeRect = toggleGroup
.append("rect")
.attr("x", margin.left)
.attr("y", 0)
.attr("width", toggleWidth / 2)
.attr("height", toggleHeight)
.attr("fill", "#3B3765")
.attr("rx", toggleHeight / 2)
.attr("ry", toggleHeight / 2);
let netApyRectLabel = toggleGroup
.append("text")
.attr("x", margin.left + toggleWidth / 4)
.attr("y", toggleHeight / 2 + 5)
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", 12)
.attr("font-weight", 700)
.text("NET APY");
let sliceApyRectLabel = toggleGroup
.append("text")
.attr("x", margin.left + toggleWidth / 4 + toggleWidth / 2)
.attr("y", toggleHeight / 2 + 5)
.attr("fill", "white")
.attr("opacity", 0.5)
.attr("text-anchor", "middle")
.attr("font-size", 12)
.attr("font-weight", 700)
.text("SLICE APY");
let hoverCircle = lineGroup
.append("circle")
.attr("r", 10)
.attr("opacity", 0)
.attr("stroke", "white")
.attr("stroke-width", 4)
.attr("fill", lineColor);
let netAApyLabel = lineGroup
.append("text")
.attr("fill", "white")
.attr("font-size", 12)
.attr("font-weight", 700)
.attr("x", width - margin.right + 10)
.attr("y", yLine(chartData.netAApy[chartData.netAApy.length - 1]) + 4)
.style("cursor", "pointer")
.style("opacity", trancheToggle ? 0.8 : 0.2)
.text("Tranche A")
.on("mousedown", function (e) {
trancheToggle = true;
selectedData = dataProps[0];
netALine.transition().duration(1000).style("opacity", 0.8);
netBLine.transition().duration(1000).style("opacity", 0.2);
netAApyLabel.transition().duration(1000).style("opacity", 1);
netBApyLabel.transition().duration(1000).style("opacity", 0.2);
updateRects();
});
let netBApyLabel = lineGroup
.append("text")
.attr("fill", "white")
.attr("font-size", 12)
.attr("font-weight", 700)
.attr("x", width - margin.right + 10)
.attr("y", yLine(chartData.netBApy[chartData.netBApy.length - 1]) + 4)
.style("cursor", "pointer")
.style("opacity", trancheToggle ? 0.2 : 0.8)
.text("Tranche B")
.on("mousedown", function (e) {
trancheToggle = false;
selectedData = dataProps[1];
netBLine.transition().duration(1000).style("opacity", 0.8);
netALine.transition().duration(1000).style("opacity", 0.2);
netAApyLabel.transition().duration(1000).style("opacity", 0.2);
netBApyLabel.transition().duration(1000).style("opacity", 1);
updateRects();
});
let toggleOverlay = toggleGroup
.append("rect")
.attr("x", margin.left)
.attr("y", 0)
.attr("width", toggleWidth)
.attr("height", toggleHeight)
.attr("opacity", 0)
.attr("rx", toggleHeight / 2)
.attr("ry", toggleHeight / 2)
.style("cursor", "pointer")
.on("mousedown", function (e) {
var offset = margin.left + toggleWidth / 2;
if (!apyToggle) offset = margin.left;
activeRect.transition().attr("x", offset);
var netOpacity = apyToggle ? 0.5 : 1;
var sliceOpacity = apyToggle ? 1 : 0.5;
netApyRectLabel.transition().attr("opacity", netOpacity);
sliceApyRectLabel.transition().attr("opacity", sliceOpacity);
apyToggle = !apyToggle;
updateLines();
});
let lineValueText = lineGroup
.append("text")
.attr("fill", "white")
.attr("font-size", 12)
.attr("text-anchor", "middle")
.attr("opacity", 0);
let lineValueTextSubtitle = lineGroup
.append("text")
.attr("fill", "white")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("opacity", 0);
let hoverRect = svg
.append("rect")
.attr("opacity", 0)
.attr("fill", "white")
.attr("x", margin.left)
.attr("y", margin.top)
.attr("width", width - margin.right - margin.left)
.attr("height", height - margin.bottom)
.on("mousemove", function (event, d) {
var index = Math.floor(hoverScale.invert(event.clientX));
updateHover(index);
})
.on("mouseout", function (event, d) {
clearHover();
});
updateRects();
updateLines();
function updateHover(index) {
if (index == hoveredIndex) return;
else hoveredIndex = index;
d3.selectAll(".bar").attr("fill", rectColor);
var activeProp = apyToggle ? "line" : "sliceLine";
d3.select(`.rect-${index}`).attr("fill", lineColor);
let xOffset = x(index) + x.bandwidth() / 2;
var date = new Date(chartData.date[index]);
var dateString = date ? dateFormat(date) : "";
hoverLine
.attr("opacity", 0.65)
.attr("x1", xOffset)
.attr("x2", xOffset)
.attr("y1", yLine(chartData[selectedData[activeProp]][index]) + 40)
.attr(
"y2",
y(chartData[selectedData.bar][index]) +
height -
rectHeight -
margin.bottom -
115
);
hoverText
.attr("opacity", 1)
.attr("x", xOffset)
.attr("y", y(chartData[selectedData.bar][index]) - 40)
.text(priceFormat(chartData[selectedData.bar][index]))
.raise();
subtitleHoverText
.attr("opacity", 0.65)
.attr("x", xOffset)
.attr("y", y(chartData[selectedData.bar][index]) - 20)
.raise();
dateText
.attr("opacity", 1)
.attr("x", xOffset)
.attr("y", height - margin.bottom + 20)
.text(dateString);
hoverCircle
.attr("opacity", 1)
.attr("cx", xOffset)
.attr("cy", yLine(chartData[selectedData[activeProp]][index]));
lineValueText
.attr("opacity", 1)
.attr("x", xOffset)
.attr("y", yLine(chartData[selectedData[activeProp]][index]) - 40)
.text(apyFormat(chartData[selectedData[activeProp]][index] / 100));
var apyTitle = apyToggle ? "NET APY" : "SLICE APY";
lineValueTextSubtitle
.attr("opacity", 0.65)
.attr("x", xOffset)
.attr("y", yLine(chartData[selectedData[activeProp]][index]) - 20)
.text(apyTitle);
}
function clearHover() {
hoverLine.attr("opacity", 0);
subtitleHoverText.attr("opacity", 0);
hoverText.attr("opacity", 0).text();
dateText.attr("opacity", 0).text();
hoverCircle.attr("opacity", 0);
lineValueText.attr("opacity", 0).text();
lineValueTextSubtitle.attr("opacity", 0);
d3.selectAll(".bar").attr("fill", rectColor);
}
return svg.node();
}