83 lines
1.7 KiB
JavaScript
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;
|