psychart
Version:
View air conditions on a psychrometric chart
192 lines (191 loc) • 7.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Chart = void 0;
/**
* Represents a generic SVG chart to be inherited by another class.
*/
var Chart = /** @class */ (function () {
/**
* Create a new instance of this chart.
* @param options Supply some options to customize this chart.
* @param defaults Supply all default options for this chart.
*/
function Chart(options, defaults) {
/**
* SVG Namespace URI
*/
this.NS = 'http://www.w3.org/2000/svg';
// Set the unique ID for this chart
this.id = Chart.id_count++;
// Set the default options
this.options = Chart.setDefaults(options, defaults);
// Create the base elements
this.base = document.createElement('div');
this.svg = document.createElementNS(this.NS, 'svg');
this.base.appendChild(this.svg);
// Set the size of the SVG element.
this.svg.setAttribute('viewBox', '0 0 ' + this.options.size.x + ' ' + this.options.size.y);
this.svg.setAttribute('width', this.options.size.x + 'px');
this.svg.setAttribute('height', this.options.size.y + 'px');
}
/**
* Produce a deep copy of an object.
* @param obj Any object
* @returns A deep copy of an object.
*/
Chart.deepCopy = function (obj) {
return JSON.parse(JSON.stringify(obj));
};
/**
* Take an object with all optional values, and set all unset values to their defaults.
* @param options An object with all parameters optional.
* @param defaults An object with all parameters default.
* @returns An object with all parameters that are unset as their default values.
*/
Chart.setDefaults = function (options, defaults) {
var _a;
var required = Chart.deepCopy(defaults);
for (var key in defaults) {
required[key] = (_a = options[key]) !== null && _a !== void 0 ? _a : defaults[key];
}
return required;
};
/**
* Remove all the children from a parent element.
* @param parent Any element to clear the children of
*/
Chart.clearChildren = function (parent) {
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
};
/**
* Generate a text element to append onto a parent element.
* @param content The contents of the text element
* @param location The location of the text element, in pixels
* @param color The fill color of the text
* @param anchor How the text is anchored relative to its location
* @returns A `<text>` element
*/
Chart.prototype.createLabel = function (content, location, color, anchor) {
var text = document.createElementNS(this.NS, 'text');
var padding = this.options.font.size / 2;
text.textContent = content;
text.setAttribute('fill', color.toString());
text.setAttribute('font-family', this.options.font.name);
text.setAttribute('font-size', this.options.font.size + 'px');
/**
* Shorthand to set all alignment properties for the text element
*/
function setProps(xPad, yPad, textAnchor, dominantBaseline) {
// Use the `x`, `y`, `text-anchor`, and `dominant-baseline` properties to set the text anchor
text.setAttribute('x', (location.x + xPad * padding) + 'px');
text.setAttribute('y', (location.y + yPad * padding) + 'px');
text.setAttribute('text-anchor', textAnchor);
text.setAttribute('dominant-baseline', dominantBaseline);
}
switch (anchor) {
case (0 /* TextAnchor.C */): {
setProps(0, 0, 'middle', 'middle');
break;
}
case (1 /* TextAnchor.NW */): {
setProps(1, 1, 'start', 'hanging');
break;
}
case (2 /* TextAnchor.N */): {
setProps(0, 1, 'middle', 'hanging');
break;
}
case (3 /* TextAnchor.NE */): {
setProps(-1, 1, 'end', 'hanging');
break;
}
case (4 /* TextAnchor.E */): {
setProps(-1, 0, 'end', 'middle');
break;
}
case (5 /* TextAnchor.SE */): {
setProps(-1, -1, 'end', 'alphabetic');
break;
}
case (6 /* TextAnchor.S */): {
setProps(0, -1, 'middle', 'alphabetic');
break;
}
case (7 /* TextAnchor.SW */): {
setProps(1, -1, 'start', 'alphabetic');
break;
}
case (8 /* TextAnchor.W */): {
setProps(1, 0, 'start', 'middle');
break;
}
default: {
throw new Error("Text anchor ".concat(anchor, " is invalid!"));
}
}
return text;
};
/**
* Draw a tooltip onto the chart.
* @param content The text content of the tooltip
* @param location The position of the tooltip
* @param color The background color
* @param parent The element to append onto
*/
Chart.prototype.drawTooltip = function (content, location, color, parent) {
var _this = this;
var base = document.createElementNS(this.NS, 'g');
var back = document.createElementNS(this.NS, 'rect');
var lines = content.split('\n').map(function (line, i) { return _this.createLabel(line, { x: 0, y: i * _this.options.font.size }, color.getContrastingColor(), 1 /* TextAnchor.NW */); });
// Append elements to the base & parent (required to compute line width)
base.appendChild(back);
base.append.apply(base, lines);
parent.append(base);
// Split the text by line and compute the size of the tooltip based on maximum line width
var padding = this.options.font.size * 0.4;
var width = Math.max.apply(Math, lines.map(function (line) { return line.getBBox().width; })) + padding * 2;
var height = lines.length * this.options.font.size + padding * 2;
// Compute the colors used in this tooltip
var background = color.toString();
var foreground = color.getContrastingColor().toString();
// Create and define styling properties for the tooltip background
back.setAttribute('stroke', foreground);
back.setAttribute('fill', background);
back.setAttribute('x', '0');
back.setAttribute('y', '0');
back.setAttribute('width', width + 'px');
back.setAttribute('height', height + 'px');
back.setAttribute('rx', padding + 'px');
back.setAttribute('stroke-width', '1px');
// Adjust the position if the background is out-of-bounds
var dx = 0, dy = 0;
if (location.x + width + padding > this.options.size.x) {
dx = -(width + padding);
}
else {
dx = padding;
}
if (location.y + height + padding > this.options.size.y) {
dy = -(height + padding);
}
else {
dy = padding;
}
base.setAttribute('transform', 'translate(' + (location.x + dx) + ',' + (location.y + dy) + ')');
};
/**
* Return the base `<div>` element for this chart to append on the parent.
* @returns The base element.
*/
Chart.prototype.getElement = function () {
return this.base;
};
/**
* Initialization counter for any chart
*/
Chart.id_count = 0;
return Chart;
}());
exports.Chart = Chart;