Published
Edited
Jul 18, 2021
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
newChart = {

// ------------- SET-UP VARS -------------
var timePeriod = 0
const svg = d3.create('svg').attr('width', width).attr('height', height)
// ------------- CREATE BASELINE GRAPH -------------
var gEntities = svg.append("g")
.attr("id", "Entities")
.selectAll("g")
.data(orderedEntities.filter(d=>d!=""))
.join("g")
.attr("id", d=>d)
.attr('transform',d=> `translate(${getEntityX(d)},${getEntityY(d)+entityHeight})`)
.call(xAxis)
//calling after the entity name or baseline does not seem to work
// add entity name as a label up top
.append("text")
.style("fill", "black")
.style("text-anchor", "middle")
.style("font-size", "12px")
.attr("x", d=> bsMg.left+ (entityWidth-bsMg.inner-bsMg.left)/2)
.attr("y", -entityHeight-10)
.html((d,i) => d)
// add baseline
var gBaseline = svg.append("g")
.attr("id", "Baseline")
.selectAll("g")
.data(orderedEntities)
.join("g")
.attr("id", d=>d)
.attr('transform',d=> `translate(${getEntityX(d)},${getEntityY(d)})`)
.call(g=>g
.append("rect")
.attr("x", d=> xScale(accountNames[0]))
.attr("y", d=> yScale(maxVal-(baselineBump+getBaselineAsset(d))))
.attr('height', d => yScale(baselineBump+getBaselineAsset(d)))
.attr('width', d=>xScale.bandwidth()*entities.includes(d))
.style('fill', baselineColor))
.style("stroke", "#FFF")
.style("stroke-width", 1)
.call(g=>g
.append("rect")
.attr("x", d=> xScale(accountNames[1]))
.attr("y", d=> yScale(maxVal-(baselineBump+getBaselineLiab(d))))
.attr('height', d => yScale(baselineBump+getBaselineLiab(d)))
.attr('width', d=>xScale.bandwidth()*entities.includes(d))
.style('fill', baselineColor)
.style("stroke", "#FFF")
.style("stroke-width", 1))
var gDataGaps = svg.append("g").attr("id", "DataGaps")
svg.select("g#DataGaps").append("g").attr("id", "AssetGaps")
svg.select("g#DataGaps").append("g").attr("id", "LiabGaps")
// ------------- BUTTONS -------------
var buttons = svg.append("g")
.attr("id", "Buttons")
.selectAll("rect")
.data(timePeriods)
.enter().append("rect");

var buttonLabels = svg.selectAll("g#Buttons")
.selectAll("text")
.data(timePeriods)
.enter().append("text");
buttons
.attr("x", (d, i) => (i%5)*2*28 + mg.left)
.attr("y", (d, i) => Math.floor(i/5)*30 )
.attr("rx", 3)
.attr("width", 50)
.attr("height", 25)
.style("fill", d => d === timePeriod ? "#212121" : "#999")
.on("mouseover", changeTime)
.on("mouseleave", mouseLeave);

buttonLabels
.style("fill", "#FFF")
.style("text-anchor", "middle")
.attr("pointer-events", "none")
.attr("x", (d, i) => (i%5)*2*28 + mg.left + 25)
.attr("y", (d, i) => Math.floor(i/5)*30 + 18)
.html((d,i) => i);

// ------------- TITLES -------------
const info = svg.append('foreignObject')
.attr('height', 50)
.attr('width', width)
.attr('x', mg.left)
.attr('y', mg.top)
.append('xhtml:div')
const infoTitle = info.append('h3')

function title() {
infoTitle.html(`${titles[timePeriod]}`)
}
// ------------- TRANSITIONS -------------
// time functions
function mouseEnter() {
d3.select(this)
.style("stroke", "#000")
.style("stroke-width", 1);
}

function mouseLeave() {
d3.select(this)
.style("stroke", "#FFF")
.style("stroke-width", 2);
}

function changeTime() {
timePeriod = d3.select(this).datum();
title();
drawCategories();
buttons.style("fill", d => d == timePeriod ? "#212121" : "#999");
}

// ------------- HOVER -------------
function hoverEntry() {
d3.select(this)
.style("stroke", "#000")
.style("stroke-width", 2);
}
function leaveEntry() {
d3.select(this)
.style("stroke", "#FFF")
.style("stroke-width", 2);
}

// ------------- CREATE GRAPH -------------
function drawCategories () {

const data = dataByTime(accumBS_data,timePeriod)
const bars = svg.select('g')
.selectAll("rect")
.data(data, d=>d.Test)
.join(
enter => enter.append('rect')
.attr('transform',d=> `translate(${getEntityX(d.Entity)},${getEntityY(d.Entity)})`)
.attr('x', d => xScale(accountNames[d.Account]))
.attr('y', d => yScale(maxVal-d.Value-baselineBump
-getCtgY(d.Entity,d.Category,d.Account,timePeriod)))
.attr('height', d => yScale(d.Value))
.attr('width', xScale.bandwidth())
.style('fill',"white")
.style("stroke", "#FFF")
.style("stroke-width", 1)
.transition().duration(1000)
.style('fill',d => getColor(d.Category))
.selection(),
update => update//.append('rect')
.transition().duration(500)
.attr('transform',d=> `translate(${getEntityX(d.Entity)},${getEntityY(d.Entity)})`)
.attr('x', d => xScale(accountNames[d.Account]))
.attr('y', d => yScale(maxVal-d.Value-baselineBump
-getCtgY(d.Entity,d.Category,d.Account,timePeriod)))
.attr('height', d => yScale(d.Value))
.attr('width', xScale.bandwidth())
.style('fill',d => getColor(d.Category))
.style("stroke", "#FFF")
.style("stroke-width", 1)
//.end()
.selection(),
exit => exit
.transition().duration(100)
.remove()
)
.on("mouseover", hoverEntry)
.on("mouseleave", leaveEntry);
//------------- IF ASSETS AND LIABILITIES ARE MISMATCHED
//CALLS FUNCTION: getGapY(time,entity,account)
const dataGaps = getBalanceSheetGaps(accumBS_data,timePeriod)
// ASSETS
const aGaps = svg.select('g#AssetGaps')
.selectAll("rect")
.data(dataGaps, d=>d.Entity)
.join(
enter => enter.append("rect").style('fill', "white")
.attr('transform',d=> `translate(${getEntityX(d.Entity)},${getEntityY(d.Entity)})`)
.transition().duration(500)
.attr("x", d=> xScale(accountNames[0]))
.attr("y", d=> yScale(maxVal-d.Assets-getGapY(timePeriod,d.Entity,0)))
.attr('height', d => yScale(d.Assets))
.attr('width', d=>xScale.bandwidth()*entities.includes(d.Entity))
.style('fill', "white")
.transition().duration(1000)
.style('stroke', gapColor)
.style("stroke-dasharray", ("3, 3"))
.selection(),
update => update.style('fill', "white")
.attr('transform',d=> `translate(${getEntityX(d.Entity)},${getEntityY(d.Entity)})`)
.transition().duration(500)
.attr("x", d=> xScale(accountNames[0]))
.attr("y", d=> yScale(maxVal-d.Assets-getGapY(timePeriod,d.Entity,0)))
.attr('height', d => yScale(d.Assets))
.attr('width', d=>xScale.bandwidth()*entities.includes(d.Entity))
.style('fill', "white")
.transition().duration(1000)
.style('stroke', gapColor)
.style("stroke-dasharray", ("3, 3"))
.selection(),
exit => exit.remove())
// LIAB
const lGaps = svg.select('g#LiabGaps')
.selectAll("rect")
.data(dataGaps, d=>d.Entity)
.join(
enter => enter.append("rect").style('fill', "white")
// .transition().duration(200)
.attr('transform',d=> `translate(${getEntityX(d.Entity)},${getEntityY(d.Entity)})`)
.transition().duration(500)
.attr("x", d=> xScale(accountNames[1]))
.attr("y", d=> yScale(maxVal-d.Liab-getGapY(timePeriod,d.Entity,1)))
.attr('height', d => yScale(d.Liab))
.attr('width', d=>xScale.bandwidth()*entities.includes(d.Entity))
.style('fill', "white")
.transition().duration(1000)
.style('stroke', gapColor)
.style("stroke-dasharray", ("3, 3"))
.selection(),
update => update.style('fill', "white")
// .transition().duration(200)
.attr('transform',d=> `translate(${getEntityX(d.Entity)},${getEntityY(d.Entity)})`)
.transition().duration(500)
.attr("x", d=> xScale(accountNames[1]))
.attr("y", d=> yScale(maxVal-d.Liab-getGapY(timePeriod,d.Entity,1)))
.attr('height', d => yScale(d.Liab))
.attr('width', d=>xScale.bandwidth()*entities.includes(d.Entity))
.style('fill', "white")
.transition().duration(1000)
.style('stroke', gapColor)
.style("stroke-dasharray", ("3, 3"))
.selection(),
exit => exit.remove())
}

title()
initialChart(svg)
return svg.node()
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
bsMgInner = width * 0.01
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dataByTime(accumBS_data,0)
Insert cell
Insert cell
Insert cell
getBalanceSheetSize(accumBS_data,1)
Insert cell
Insert cell
function getGapY(time,entity,account) {
const bsSize = getBalanceSheetSize(accumBS_data,time)
const e = bsSize.find(d=> d.Entity == entity)
return baselineBump + ((account==0) ? e.Assets : e.Liab)
}
Insert cell
getGapY(1,"CH-Bank",0)
Insert cell
getBalanceSheetGaps(accumBS_data,1)
Insert cell
getBalanceSheetSize(accumBS_data,5)
Insert cell
dataByTime(accumBS_data,1)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
baselineData = createBaseline(0)
Insert cell
createBaseline(0)
Insert cell
Insert cell
Insert cell
d3 = require('d3@6')
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more