You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.5 KiB
JavaScript

class PlotWidget extends BaseWidget {
$el;
#cv;
constructor(data, renderer) {
super(data, renderer);
this.makeLayout({
type: 'div',
class: '',
children: [
{
type: 'canvas',
name: 'el',
}
]
});
this.#cv = new Plot(data.id, this.$el, data.height ?? 150, data.text, data.type, true);
this.$el.parentNode.addEventListener('resize', () => {
this.#cv.resize();
});
wait2Frame().then(() => {
this.#cv.redraw();
});
this.update(data.value);
}
update(data) {
super.update(data);
if ('value' in data) {
this.#cv.update(data.value);
this.#cv.redraw();
}
}
close() {
this.#cv.stop();
}
}
Renderer.register('plot', PlotWidget);
class Plot {
constructor(id, cv, height, labels, type, dark) {
this.id = id;
this.cv = cv;
this.height = height;
this.labels = labels ? labels.split(';') : null;
this.type = type;
this.dark = dark;
this.data = [];
this.resize();
cv.onclick = (event) => this._click(event);
if ("ontouchstart" in document.documentElement) {
document.addEventListener("touchmove", this._onTouchMove, { passive: false });
} else {
document.addEventListener("mousemove", this._onMouseMove);
}
}
stop() {
if ("ontouchstart" in document.documentElement) {
document.removeEventListener("touchmove", this._onTouchMove);
} else {
document.removeEventListener("mousemove", this._onMouseMove);
}
}
clear() {
this.data = [];
}
resize() {
let cv = this.cv;
let rw = cv.parentNode.clientWidth;
if (!rw) return;
let r = window.devicePixelRatio;
cv.style.width = rw + 'px';
cv.style.height = this.height + 'px';
cv.width = Math.floor(rw * r);
cv.height = Math.floor(this.height * r);
this.redraw(this.data);
}
update(data) {
this.data = this.data.concat(data);
}
redraw() {
let cv = this.cv;
let cx = cv.getContext("2d");
let r = window.devicePixelRatio;
cx.fillRect(0, 0, cv.width, cv.height);
}
// PRIVATE
_click(e) {
let rect = this.cv.getBoundingClientRect();
let x = Math.round(e.clientX - rect.left);
if (x < 0) x = 0;
let y = Math.round(e.clientY - rect.top);
if (y < 0) y = 0;
}
_onTouchMove = (event) => {
event.preventDefault();
for (let t of event.changedTouches) {
if (t.target === this.cv) this._move(t);
}
}
_onMouseMove = (event) => {
if (event.target == this.cv) this._move(event);
}
_move(rect) {
let x = rect.pageX;
let y = rect.pageY;
if (this.cv.offsetParent.tagName.toUpperCase() === "BODY") {
x -= this.cv.offsetLeft;
y -= this.cv.offsetTop;
} else {
x -= this.cv.offsetParent.offsetLeft;
y -= this.cv.offsetParent.offsetTop;
}
x = this._constrain(x, 0, this.cv.width / window.devicePixelRatio);
y = this._constrain(y, 0, this.cv.height / window.devicePixelRatio);
this.redraw();
}
_constrain(x, min, max) {
if (x < min) return min;
if (x > max) return max;
return x;
}
};