@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
217 lines (163 loc) • 5.35 kB
JavaScript
import { passThrough } from "../../../core/function/passThrough.js";
import { clamp01 } from "../../../core/math/clamp01.js";
import BoundedValue from "../../../core/model/BoundedValue.js";
import { frameThrottle } from "../../../engine/graphics/FrameThrottle.js";
import dom from "../../DOM.js";
import View from "../../View.js";
/**
*
* @param {number} value
* @param {number} max
* @param {function(number):string} process
* @returns {string}
*/
function makeTextPercentage(value, max, process) {
const r = (value / max) * 100;
const x = process(r);
return `${x}%`;
}
/**
*
* @param {number} value
* @param {number} max
* @param {function(number):string} process
* @returns {string}
*/
function makeTextAbsolute(value, max, process) {
const _max = process(max);
const _val = process(value);
return `${_val} / ${_max}`;
}
class ProgressBarView extends View {
/**
*
* @param {number[]|BoundedValue} [model]
* @param {string[]} [classList]
* @param {boolean} [displayLabel]
* @param {string} [displayLabelType]
* @param {boolean} [displayTipMarker]
* @param {function(number):string} [process]
*/
constructor(model, {
classList = [],
displayLabel = false,
displayLabelType = 'percent',
displayTipMarker = true,
process = passThrough
} = {}) {
super();
this.model = model;
const dRoot = dom().addClass('progress-bar');
this.el = dRoot.el;
this.addClasses(classList);
/**
* @type {HTMLElement}
*/
this.__el_fill = dRoot.createChild().addClass('fill').el;
this.__el_fill_container = document.createElement('div');
this.__el_fill_container.classList.add('fill-container');
this.__el_fill_container.appendChild(this.__el_fill);
this.el.appendChild(this.__el_fill_container);
let dLabel = null;
if (displayLabel === true) {
dLabel = dom(this.el).createChild('div').addClass('label').css({ height: "inherit" });
}
this.__display_tip_marker = displayTipMarker;
if (displayTipMarker) {
this.__el_tip_marker = document.createElement('div');
this.__el_tip_marker.classList.add('tip-marker');
this.el.appendChild(this.__el_tip_marker);
}
/**
*
* @type {function}
* @private
*/
this.__process = process;
/**
*
* @type {boolean}
* @private
*/
this.__display_label_enabled = displayLabel;
/**
*
* @type {string}
* @private
*/
this.__display_label_type = displayLabelType;
/**
*
* @type {null|DOM}
* @private
*/
this.__dom_label = dLabel;
this.__value_current = 0;
this.__value_max = 0;
this.__throttled_render = frameThrottle(this.render, this);
if (model instanceof BoundedValue) {
this.on.linked.add(this.__updateFromBoundedValue, this);
this.bindSignal(model.on.changed, this.__updateFromBoundedValue, this);
} else if (model instanceof Array) {
this.on.linked.add(this.__updateFromArray, this);
this.bindSignal(model[0].onChanged, this.__updateFromArray, this);
this.bindSignal(model[1].onChanged, this.__updateFromArray, this);
}
}
get value() {
return this.__value_current;
}
set value(v) {
if (v === this.__value_current) {
return;
}
this.__value_current = v;
this.__throttled_render();
}
get max() {
return this.__value_max;
}
set max(v) {
if (v === this.__value_max) {
return;
}
this.__value_max = v;
this.__throttled_render();
}
render() {
const value = this.__value_current;
const max = this.__value_max;
const style = this.__el_fill.style;
//sanitize input to be in range 0 to 1
const fill = clamp01(value / max);
const fill_percent_string = (fill * 100) + "%";
style.width = fill_percent_string;
const dLabel = this.__dom_label;
if (dLabel !== null) {
//update label text
if (this.__display_label_type === "absolute") {
dLabel.text(makeTextAbsolute(value, max, this.__process));
} else {
dLabel.text(makeTextPercentage(value, max, this.__process));
}
}
if (this.__display_tip_marker) {
this.__el_tip_marker.style.left = fill_percent_string;
}
}
/**
* @private
*/
__updateFromArray() {
this.value = this.model[0].getValue();
this.max = this.model[1].getValue();
}
/**
* @private
*/
__updateFromBoundedValue() {
this.value = this.model.getValue();
this.max = this.model.getUpperLimit();
}
}
export default ProgressBarView;