@obliczeniowo/elementary
Version:
Library made in Angular version 20
242 lines (236 loc) • 11.7 kB
JavaScript
import * as i0 from '@angular/core';
import { Input, ViewChild, Component, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DrawingPdfInterface } from '@obliczeniowo/elementary/drawing-pdf';
import { TextAlign, DrawingSvgInterface, Rect } from '@obliczeniowo/elementary/drawing';
import { ColorHSV, Point2D } from '@obliczeniowo/elementary/classes';
import { ElementaryMath } from '@obliczeniowo/elementary/math';
import { keys } from '@obliczeniowo/elementary/objects';
import * as i1 from '@obliczeniowo/elementary/buttons';
import { ButtonsModule } from '@obliczeniowo/elementary/buttons';
class FlatPieDiagram {
dc;
areaRect;
keyValues = {};
dr = 0;
ray = 100;
valueKeyFormat = (index, value, sum, key) => `${value} (${(value / sum * 100).toFixed(2)}%)`;
colors = (index, value, max, count) => ({
fill: ColorHSV.createColorHSV(((360 / count) * 2 * index) / 2, 0.5, 255).convertToRGB().getHexColorBase,
stroke: ColorHSV.createColorHSV(((360 / count) * 2 * index) / 2, 0.35, 255).convertToRGB().getHexColorBase,
line: ColorHSV.createColorHSV(((360 / count) * 2 * index) / 2, 0.35, 150).convertToRGB().getHexColorBase,
text: ColorHSV.createColorHSV(((360 / count) * 2 * index) / 2, 0.65, 200).convertToRGB().getHexColorBase
});
constructor(dc, area) {
this.dc = dc;
this.areaRect = area;
}
sum() {
let sum = 0;
keys(this.keyValues).forEach((key) => sum += this.keyValues[key]);
return sum;
}
minMax() {
const minMax = { min: 0, max: 0 };
return keys(this.keyValues).reduce((prev, curr) => (prev = prev
? {
min: Math.min(prev.min, this.keyValues[curr]), max: Math.max(prev.max, this.keyValues[curr])
}
: {
min: this.keyValues[curr],
max: this.keyValues[curr]
},
prev), minMax);
}
draw(dc = this.dc) {
dc.clear();
const sum = this.sum();
let start = 0;
let da = 0;
const center = new Point2D(this.areaRect.width / 2, this.areaRect.height / 2);
this.ray = Math.min(this.areaRect.width, this.areaRect.height) / 3;
const minMax = this.minMax();
const length = keys(this.keyValues).length;
if (sum) {
const options = [];
let leftTopIndex = 0;
let rightTopIndex = 0;
let leftBottomIndex = 0;
let rightBottomIndex = 0;
const dk = ElementaryMath.degreesToRadians(10);
keys(this.keyValues).forEach((key, oIndex) => {
da = this.keyValues[key] / sum * Math.PI * 2;
const right = start + da / 2 < Math.PI / 2 || start + da / 2 > 3 * Math.PI / 2;
const bottom = start + da / 2 < Math.PI;
let index = 0;
if (da < dk) {
if (!right && !bottom) {
leftTopIndex += 1;
index = leftTopIndex;
}
else if (right && !bottom) {
rightTopIndex += 1;
index = rightTopIndex;
}
else if (!right && bottom) {
leftBottomIndex += 1;
index = leftBottomIndex;
}
else if (right && bottom) {
rightBottomIndex += 1;
index = rightBottomIndex;
}
}
options.push({
start,
da,
right,
bottom,
index,
colors: this.colors(oIndex, this.keyValues[key], minMax, length)
});
start += da;
});
start = 0;
keys(this.keyValues).forEach((key, index) => {
da = this.keyValues[key] / sum * Math.PI * 2;
const rotatedPoint = center.add(new Point2D(this.dr, 0).rotate(start + da / 2));
dc.drawPie(rotatedPoint, this.ray, this.ray, start, start + da > Math.PI * 2 ? Math.PI * 2 : start + da, 1, options[index].colors.stroke, options[index].colors.fill);
start += da;
});
start = 0;
keys(this.keyValues).forEach((key, index) => {
da = this.keyValues[key] / sum * Math.PI * 2;
const text = this.valueKeyFormat(index, this.keyValues[key], sum, key);
const startPoint = center.add(new Point2D(this.dr + this.ray * 0.9).rotate(start + da / 2));
dc.setFontSize(8);
if (da < dk) {
let dy = 0;
const angle = options[index];
if (!angle.right && !angle.bottom) {
dy = leftTopIndex * 12;
}
else if (angle.right && !angle.bottom) {
dy = (angle.index * 2 - 1) * 12;
}
else if (!angle.right && angle.bottom) {
dy = (angle.index * 2 - 1) * 12;
}
else if (angle.right && angle.bottom) {
dy = rightBottomIndex * 12;
}
dy = this.ray - dy;
const end = center.add(new Point2D(options[index].right ? (this.ray * 1.2) : -this.ray * 1.2, options[index].bottom ? options[index].index * 12 + dy : -options[index].index * 12 - dy));
dc.drawLine(startPoint, end, 1, options[index].colors.line)
.setTextAlign(angle.right && TextAlign.LEFT || TextAlign.RIGHT)
.drawText(text, end.add(new Point2D(angle.right && 2 || -2, 2)), options[index].colors.text, 0);
}
else {
const textAngle = -180 / Math.PI * (start + da / 2);
dc.setTextAlign(options[index].right ? TextAlign.RIGHT : TextAlign.LEFT)
.drawText(text, startPoint, options[index].colors.text, textAngle < -90 && textAngle > -270 ? textAngle + 180 : textAngle);
}
start += da;
});
}
}
}
class FlatPieDiagramComponent {
renderer;
drawing;
width = 800;
height = 528;
pData = {};
get data() {
return this.pData;
}
set data(value) {
this.pData = value;
if (this.drawing) {
this.drawing.keyValues = this.pData;
this.drawing.draw();
}
}
svg;
_colors;
_valueKeyFormat = (index, value, sum, key) => `${value} (${(value / sum * 100).toFixed(2)}%)`;
set valueKeyFormat(valueKeyFormat) {
if (valueKeyFormat) {
this._valueKeyFormat = valueKeyFormat;
if (this.drawing) {
this.drawing.valueKeyFormat = valueKeyFormat;
this.drawing.draw();
}
}
}
set colors(colors) {
if (colors) {
this._colors = colors;
if (this.drawing) {
this.drawing.colors = colors;
this.drawing.draw();
}
}
}
constructor(renderer) {
this.renderer = renderer;
}
ngAfterViewInit() {
this.drawing = new FlatPieDiagram(new DrawingSvgInterface(this.svg.nativeElement, this.renderer), new Rect(new Point2D(0, 0), new Point2D(this.width, this.height)));
this.drawing.keyValues = this.pData;
if (this._valueKeyFormat) {
this.drawing.valueKeyFormat = this._valueKeyFormat;
}
if (this._colors) {
this.drawing.colors = this._colors;
}
this.drawing.draw();
}
pdf() {
const dc = new DrawingPdfInterface(this.drawing.areaRect);
this.drawing.draw(dc);
dc.save('flat-pie-diagram');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FlatPieDiagramComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.4", type: FlatPieDiagramComponent, isStandalone: false, selector: "obl-flat-pie-diagram", inputs: { data: "data", valueKeyFormat: "valueKeyFormat", colors: "colors" }, viewQueries: [{ propertyName: "svg", first: true, predicate: ["diagram"], descendants: true }], ngImport: i0, template: "<div class=\"svgContainer\">\n <svg #diagram [attr.viewBox]=\"'0 0 ' + width + ' ' + height\"></svg>\n\n <button class=\"pdf-button\" oblButton icon=\"file\" (click)=\"pdf()\">\n </button>\n</div>\n", styles: [":host .svgContainer{overflow:auto;max-width:100%;position:relative}:host .svgContainer .pdf-button{position:absolute;right:20px;top:20px;display:none}:host .svgContainer:hover .pdf-button{display:block}\n"], dependencies: [{ kind: "directive", type: i1.ButtonDirective, selector: "oblButton, [oblButton]", inputs: ["oblButton", "icon", "blockWhenLoading", "loading", "toggle", "selected", "link", "target"], exportAs: ["oblButton"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FlatPieDiagramComponent, decorators: [{
type: Component,
args: [{ selector: 'obl-flat-pie-diagram', standalone: false, template: "<div class=\"svgContainer\">\n <svg #diagram [attr.viewBox]=\"'0 0 ' + width + ' ' + height\"></svg>\n\n <button class=\"pdf-button\" oblButton icon=\"file\" (click)=\"pdf()\">\n </button>\n</div>\n", styles: [":host .svgContainer{overflow:auto;max-width:100%;position:relative}:host .svgContainer .pdf-button{position:absolute;right:20px;top:20px;display:none}:host .svgContainer:hover .pdf-button{display:block}\n"] }]
}], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { data: [{
type: Input
}], svg: [{
type: ViewChild,
args: ['diagram']
}], valueKeyFormat: [{
type: Input
}], colors: [{
type: Input
}] } });
class FlatPieDiagramModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FlatPieDiagramModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: FlatPieDiagramModule, declarations: [FlatPieDiagramComponent], imports: [CommonModule,
ButtonsModule], exports: [FlatPieDiagramComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FlatPieDiagramModule, imports: [CommonModule,
ButtonsModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FlatPieDiagramModule, decorators: [{
type: NgModule,
args: [{
declarations: [
FlatPieDiagramComponent
],
imports: [
CommonModule,
ButtonsModule
],
exports: [
FlatPieDiagramComponent
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { FlatPieDiagram, FlatPieDiagramComponent, FlatPieDiagramModule };
//# sourceMappingURL=obliczeniowo-elementary-flat-pie-diagram.mjs.map