systemquery/src/static/js/ui/charts/ChartStackedBar.mjs

83 lines
1.7 KiB
JavaScript

"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 categories of this bar.
* @type {Object[]}
*/
this.categories = [
// { name: "Some category name", 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} name A display name for 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(name, colour, weight) {
const id = Symbol();
this.categories.push({
id,
name,
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
}
}
export default ChartStackedBar;