diff --git a/src/static/js/ui/charts/ChartStackedBar.mjs b/src/static/js/ui/charts/ChartStackedBar.mjs index e563881..75422df 100644 --- a/src/static/js/ui/charts/ChartStackedBar.mjs +++ b/src/static/js/ui/charts/ChartStackedBar.mjs @@ -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 } }