<section id="bars-with-percentages">
<h1>Bars with percentages</h1>
<p>the bar height is the total count and then a percentage of the bar is overlaid on top of the bar</p>
<button id="trigger">Load data</button>
<div class="block">
<h2>The SVG Output</h2>
<p>Hover on bars for property title</p>
<div id="svgOutput"></div>
</div>
</section>
<div class="templates">
<template id="result_box">
<div class="results_box">
<div class="result">
<span class="property"></span>: <span class="count"></span>
</div>
</div>
</template>
</div>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="../../js/components/bars-with-percentages.js"></script>
<section id="bars-with-percentages">
<h1>Bars with percentages</h1>
<p>the bar height is the total count and then a percentage of the bar is overlaid on top of the bar</p>
<button id="trigger">Load data</button>
<div class="block">
<h2>The SVG Output</h2>
<p>Hover on bars for property title</p>
<div id="svgOutput"></div>
</div>
{{!--
<div class="block">
<h2>The text output</h2>
<div id="outputBox"></div>
</div>
--}}
</section>
<div class="templates">
<template id="result_box">
<div class="results_box">
<div class="result">
<span class="property"></span>: <span class="count"></span>
</div>
</div>
</template>
</div>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="{{ path '/js/components/bars-with-percentages.js' }}"></script>
/* No context defined. */
(function () {
document.addEventListener('DOMContentLoaded', function () {
console.log("bars-with-percentages active");
const button = document.querySelector('#trigger');
// const outputBox = document.querySelector('#outputBox');
const svgOutput = document.querySelector('#svgOutput');
button.addEventListener('click', function() {
const spinnerA = document.createElement('div');
spinnerA.classList.add('spinner');
// outputBox.appendChild(spinnerA);
const spinnerB = document.createElement('div');
spinnerB.classList.add('spinner');
svgOutput.appendChild(spinnerB);
fetch('https://my.api.mockaroo.com/chart_data_2.json?count=10&key=0b401b10')
.then(response => response.json())
.then(data => {
// outputBox.removeChild(spinnerA);
svgOutput.removeChild(spinnerB);
data.sort(function (x, y) {
return d3.ascending(x.date, y.date);
})
// d3 version of results
const w = 1000;
const h = 500;
const padding = 40;
const svg = d3.select("#svgOutput")
.append("svg");
svg.attr("viewBox", [0, 0, w, h])
.attr("preserveAspectRatio", "xMidYMid meet");
// const yScale = d3.scaleLinear()
// .domain([0, d3.max(data, (d) => d.count)])
// .range([h - padding, padding]);
const yScale = d3.scaleLinear()
.domain([0, 900])
.range([h - padding, padding]);
const xScale = d3.scaleLinear()
.domain([0, data.length])
.range([padding, w - (0.25 * padding)]);
console.log(xScale(0));
console.log(xScale(5));
console.log(xScale(10));
svg.selectAll("rect.bar")
.data(data)
.join('rect')
.attr('class', 'bar')
.attr('x', (d, i) => {
return i * ((w - (1.25 * padding)) / data.length) + 1 + padding;
})
.attr("y", (d) => {
return yScale(d.count);
})
.attr("width", () => {
return ((w - (1.25 * padding)) / data.length) - 4;
})
.attr("height", (d) => {
return yScale(0) - yScale(d.count);
})
.attr("data-count", (d) => (d.count))
.append('title')
.text((d) => d.date);
svg.selectAll("rect.percentage-bar")
.data(data)
.join('rect')
.attr('class', 'percentage-bar')
.attr('x', (d, i) => {
return i * ((w - (1.25 * padding)) / data.length) + padding;
})
.attr("y", (d) => {
return yScale(d.count);
})
.attr("width", () => {
return ((w - (1.25 * padding)) / data.length) - 2;
})
.attr("height", (d) => {
return (yScale(0) - yScale(d.count)) * d.percentage;
})
.append('title')
.text((d) => d.percentage);
svg.selectAll("text.count")
.data(data)
.join("text")
.attr('class', 'count')
.text((d) => (d.count))
.attr('x', (d, i) => {
return i * ((w - (1.25 * padding)) / data.length) - 4 + padding + 10;
})
.attr("y", (d) => {
return yScale(d.count) - 10;
})
.style('font-size', '1rem')
.style('font-weight', 'bold')
.style('font-family', 'Courier New')
.style('fill', 'navy');
svg.selectAll("text.date")
.data(data)
.join("text")
.attr('class', 'date')
.text((d) => (d.date))
.attr('x', (d, i) => {
return i * ((w - (1.25 * padding)) / data.length) - 4 + padding + 10;
})
.attr("y", (d) => {
return h - 20;
})
.style('font-size', '0.75rem')
.style('font-weight', 'bold')
.style('font-family', 'Courier New')
.style('fill', 'navy');
// xAxis
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", "translate(0, " + (h - padding) + ")")
.call(xAxis)
.call(g => {
console.dir(g);
g.selectAll(".tick text")
.attr("dy", "10000");
});
// yAxis - adding last so it appears above the bars
const yAxis = d3.axisRight(yScale)
.tickSize(w - (padding * 1.25));
svg.append("g")
.attr("transform", "translate(" + padding + ", 0)")
.call(yAxis)
.call(g => g.selectAll(".tick:not(:first-of-type) line")
.attr("stroke-opacity", 0.5)
.attr("stroke-dasharray", "4,8"))
.call(g => g.selectAll(".tick line"))
.attr("stroke", "navy")
.call(g => g.selectAll(".tick text")
.attr("x", -24)
.attr("dy", -4));
// text version of results
// data.forEach(function(item) {
// let template = document.querySelector('#result_box');
// let resultBox = document.importNode(template.content, true);
//
// resultBox.querySelector('.date').innerHTML = item.date;
// resultBox.querySelector('.count').innerHTML = item.count;
//
// outputBox.appendChild(resultBox);
// })
})
})
});
})();
#bars-with-percentages {
@keyframes spin {
0% {
transform: rotate(0);
}
100% {
transform: rotate(180deg);
}
}
#outputBox {
margin: 2rem 0;
padding: 2rem;
border: 2px solid aliceblue;
}
.spinner {
width: 4px;
height: 40px;
background-color: darkcyan;
animation: 0.75s ease-in-out both alternate infinite spin;
}
.results_box {
margin: 0 0 1rem 0;
.property {
font-weight: bold;
}
}
#svgOutput {
margin: 2rem 0;
}
svg {
display: block;
width: calc(100% - 2px - 2rem);
margin: auto;
height: auto;
border: 1px solid navy;
background-color: azure;
.bar {
fill: yellow;
fill-opacity: 0.8;
stroke: darkslategray;
stroke-width: 1px;
}
.percentage-bar {
fill: yellowgreen;
fill-opacity: 1;
}
}
.block {
margin: 2rem 0;
padding: 2rem 0;
border-top: 1px solid cadetblue;
}
}
No notes defined.