Add helper class to manage a set of stacked bars
It also automatically generates and manages the legend.
This commit is contained in:
parent
0f37853aba
commit
6b2aab3391
2 changed files with 55 additions and 7 deletions
|
@ -15,28 +15,30 @@ class ChartStackedBar {
|
||||||
* @type {Object[]}
|
* @type {Object[]}
|
||||||
*/
|
*/
|
||||||
this.categories = [
|
this.categories = [
|
||||||
// { colour: "hsl(46, 80%, 50%)", weight: 4 }
|
// { name: "Some category name", colour: "hsl(46, 80%, 50%)", weight: 4 }
|
||||||
// ....
|
// ....
|
||||||
];
|
];
|
||||||
|
|
||||||
this.auto_render = true;
|
this.auto_render = true;
|
||||||
|
|
||||||
|
|
||||||
this.#svg = SVG().size("100%", "100%");
|
this.svg = SVG().size("100%", "100%");
|
||||||
|
|
||||||
this.sym_bar = Symbol();
|
this.sym_bar = Symbol();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new category to the bar.
|
* Adds a new category to the bar.
|
||||||
* @param {string} colour The colour to assign to the category.
|
* @param {string} name A display name for the category.
|
||||||
* @param {number} weight The weighting value to assign to the category.
|
* @param {string} colour The colour to assign to the category.
|
||||||
|
* @param {number} weight The weighting value to assign to the category.
|
||||||
|
* @returns {Symbol} A unique id for the new category.
|
||||||
*/
|
*/
|
||||||
category_add(colour, weight) {
|
category_add(name, colour, weight) {
|
||||||
const id = Symbol();
|
const id = Symbol();
|
||||||
this.categories.push({
|
this.categories.push({
|
||||||
id,
|
id,
|
||||||
|
name,
|
||||||
colour,
|
colour,
|
||||||
weight,
|
weight,
|
||||||
[this.sym_bar]: null
|
[this.sym_bar]: null
|
||||||
|
@ -61,7 +63,7 @@ class ChartStackedBar {
|
||||||
for(const cat of this.categories) {
|
for(const cat of this.categories) {
|
||||||
const percent_this = this.#weight_percent(cat.weight);
|
const percent_this = this.#weight_percent(cat.weight);
|
||||||
if(cat[this.sym_bar] === null) {
|
if(cat[this.sym_bar] === null) {
|
||||||
cat[this.sym_bar] = this.#svg.rect("100%", "10%")
|
cat[this.sym_bar] = this.svg.rect("100%", "10%")
|
||||||
.fill(cat.colour)
|
.fill(cat.colour)
|
||||||
}
|
}
|
||||||
cat[this.sym_bar].height = `${percent_this}%`;
|
cat[this.sym_bar].height = `${percent_this}%`;
|
||||||
|
|
46
src/static/js/ui/charts/ChartStackedBarSet.mjs
Normal file
46
src/static/js/ui/charts/ChartStackedBarSet.mjs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
import Emel from 'emel';
|
||||||
|
|
||||||
|
class ChartStackedBarSet {
|
||||||
|
constructor() {
|
||||||
|
this.emel = new Emel().emel;
|
||||||
|
|
||||||
|
this.el = this.emel(`div[class="stacked-bar-set"]>div[class=legend]+div[class=bars]`);
|
||||||
|
|
||||||
|
this.bars = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
add_bar(i, bar) {
|
||||||
|
this.bars.splice(i, 0, bar);
|
||||||
|
this.#update_cats();
|
||||||
|
}
|
||||||
|
|
||||||
|
#update_cats() {
|
||||||
|
const el_legend = this.el.querySelector(`.legend`);
|
||||||
|
const els_legend_items = [...el_legend.querySelectorAll(`.legend-item`)];
|
||||||
|
|
||||||
|
// map → flatten → uniq
|
||||||
|
let cats = this.bars.map(bar => bar.categories).flat()
|
||||||
|
.filter((cat, i) => cats.find(scat => cat.name === scat.name) === i);
|
||||||
|
|
||||||
|
for(const cat of cats) {
|
||||||
|
const el_legend_item = els_legend_items.find(el => el.dataset.name === cat.name);
|
||||||
|
if(typeof el_legend_item === "undefined") {
|
||||||
|
// Nope, didn't find it - create it
|
||||||
|
el_legend.appendChild(this.#make_legend_item(cat.colour, cat.name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Yep, we found it - update the names
|
||||||
|
el_legend_item.querySelector(".legend-item-spot").style.background = cat.colour;
|
||||||
|
el_legend_item.querySelector(".legend-item-text").replaceChildren(document.createTextNode(cat.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#make_legend_item(colour, name) {
|
||||||
|
return this.emel(`span[class="legend-item"]>span[style="background: ${colour};" class="legend-item-spot"]+span[class="legend-item-text"]{${name}}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChartStackedBarSet;
|
Loading…
Reference in a new issue