EoQ_Supporting_Files/index4bar.html

160 lines
3.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Bar Chart - Numeric Keys</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
body {
font-family: sans-serif;
margin: 40px;
}
.bar {
fill: steelblue;
stroke: black;
stroke-width: 1px;
}
.axis path,
.axis line {
stroke: black;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<svg width="600" height="250"></svg>
<script>
const svg = d3.select("svg");
const width = +svg.attr("width");
const height = +svg.attr("height");
const margin = { top: 40, right: 30, bottom: 60, left: 30 };
const data = {
"-3": 0,
"-2": 1,
"-1": 3,
"0": 0,
"1": 2,
"2": 0,
"3": 10
};
const dataArray = Object.entries(data).map(([key, count]) => ({
key: +key,
count: count
}));
const x = d3.scaleBand()
.domain([-3,-2,-1,0,1,2,3])
.range([margin.left, width - margin.right])
.padding(0);
const y = d3.scaleLinear()
.domain([0, d3.max(dataArray, d => d.count)])
.nice()
.range([height - margin.bottom, margin.top]);
// X Axis
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x)
.tickSize(0))
.selectAll("text")
.attr("x", 0)
.attr("y", 10)
.style("text-anchor", "middle")
.style("font-size", "12px");
// Add the required ticks
const xTicks = d3.scaleLinear()
.domain([-3.5, 3.5])
.range([margin.left, width - margin.right]);
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(xTicks).tickValues(d3.range(-3.5, 4, 1)))
.selectAll("text")
.style("visibility", "hidden"); // This hides the labels
// Y Axis
//svg.append("g")
// .attr("transform", `translate(${margin.left},0)`)
// .call(d3.axisLeft(y).ticks(5));
// Bars
svg.selectAll(".bar")
.data(dataArray)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", d => x(d.key))
.attr("y", d => y(d.count))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.count));
// Labels
svg.selectAll(".label")
.data(dataArray)
.enter()
.append("text")
.attr("x", d => x(d.key) + x.bandwidth() / 2)
.attr("y", d => d.count > 0 ? y(d.count) - 5 : y(0))
.attr("text-anchor", "middle")
.attr("font-size", "12px")
.attr("fill", "black")
.text(d => d.count > 0 ? d.count : "");
// Average line
const format = d3.format(".2f");
const totalCount = d3.sum(dataArray, d => d.count);
const weightedSum = d3.sum(dataArray, d => d.key * d.count);
const average = totalCount > 0 ? format(weightedSum / totalCount) : 0;
const xLinear = d3.scaleLinear()
.domain([-3, 3])
.range([margin.left + x.bandwidth() / 2, width - margin.right - x.bandwidth() / 2]);
const avgX = xLinear(average);
svg.append("line")
.attr("x1", avgX)
.attr("x2", avgX)
.attr("y1", y(0))
.attr("y2", y(d3.max(dataArray, d => d.count)) - 20)
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "4,2");
svg.append("text")
.attr("x", avgX)
.attr("y", y(d3.max(dataArray, d => d.count)) - 30)
.attr("text-anchor", "middle")
.attr("fill", "red")
.attr("font-size", "12px")
.text("Average ("+average+")");
// Title beneath the graph
svg.append("text")
.attr("x", width / 2)
.attr("y", height - 5) // Just below the x-axis
.attr("text-anchor", "middle")
.attr("font-size", "14px")
.attr("fill", "black")
.text("Demo bar graph");
</script>
</body>
</html>