ChartStackedBar: implement, but make it a simple unlabelled bar.

We can put the legend elsewhere, and manage multiple bars with a CSS 
grid or something.
This commit is contained in:
Starbeamrainbowlabs 2022-05-07 01:32:04 +01:00
parent 0e2f68a067
commit 0f37853aba
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
1 changed files with 61 additions and 19 deletions

View File

@ -1,37 +1,79 @@
"use strict";
import { SVG } from 'svg.js';
class ChartStackedBar {
get weight_total() {
return this.categories.reduce((cat, acc) => cat.weight + acc, 0);
}
constructor(el) {
this.el = el;
/**
* The category names and their properties.
* The categories of this bar.
* @type {Object[]}
*/
this.categories = [
// { name: "Some category name", colour: "hsl(46, 80%, 50%)" }
// ....
]
/**
* Whether to normalise all bars to be the same height or not.
* @type {Boolean}
*/
this.percentage = false;
/**
* The bars to render.
* Additional properties can be specified on the objects passed and
* this class will ignore them. It's strongly recommended though that
* any additional properties start with an underscore.
* @type {Object[]}
*/
this.bars = [
// { name: "bar name 1", values: [ { value: 3, cat: 1 }, .... ] }
// { colour: "hsl(46, 80%, 50%)", weight: 4 }
// ....
];
this.auto_render = true;
this.#svg = SVG().size("100%", "100%");
this.sym_bar = Symbol();
}
/**
* Adds a new category to the bar.
* @param {string} colour The colour to assign to the category.
* @param {number} weight The weighting value to assign to the category.
*/
category_add(colour, weight) {
const id = Symbol();
this.categories.push({
id,
colour,
weight,
[this.sym_bar]: null
});
if(this.auto_render) this.render();
return id;
}
category_remove(id) {
for(const i in this.categories) {
if(this.categories[i].id === id) {
this.categories.splice(i, 1);
if(this.auto_render) this.render();
return true;
}
}
return false;
}
render() {
let percent_so_far = 0;
for(const cat of this.categories) {
const percent_this = this.#weight_percent(cat.weight);
if(cat[this.sym_bar] === null) {
cat[this.sym_bar] = this.#svg.rect("100%", "10%")
.fill(cat.colour)
}
cat[this.sym_bar].height = `${percent_this}%`;
cat[this.sym_bar] = cat[this.sym_bar].fill(cat.colour)
.move("0%", `${percent_so_far}%`);
percent_so_far += percent_this;
}
}
#weight_percent(weight) {
return (weight / this.weight_total) * 100
}
}