UNPKG

@obliczeniowo/elementary

Version:
185 lines (180 loc) 9.95 kB
import * as i1 from '@obliczeniowo/elementary/svg'; import { SvgModule } from '@obliczeniowo/elementary/svg'; import * as i0 from '@angular/core'; import { EventEmitter, Output, Input, ChangeDetectionStrategy, Component, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ElementaryMath } from '@obliczeniowo/elementary/math'; import { Point2D } from '@obliczeniowo/elementary/classes'; class SimpleDiagram2DComponent { element; svg; /** * Points2D array table as diagram points */ points = []; /** * Gradient definition description including: * array of: * - colors; * - opacity; * - offset; * coordinates of gradient: * - x, y start/end position (optional) */ gradient; /** * When undefined or not set it will 1 on X is 100% object width, and similar on Y * When 'userSpaceOnUse' it use space units system (not related to object size) */ gradientUnits; /** * diagram padding */ padding = 0; /** * bottom diagram padding (includes as part of diagram shape) */ diagramBottomPadding = 5; /** */ height = 50; /** */ width = 200; /** * When set to true emit cursor position value in diagram space coordinates */ interactive = false; /** * Emit when require recalculation */ recalculate = new EventEmitter(); hover = new EventEmitter(); convertedShape = ''; convertedLines = ''; gradientId = `SimpleDiagram2D-${Math.floor(Math.random() * 100000)}`; xMinMax; yMinMax; dx; dy; sx; sy; constructor(element) { this.element = element; } ngOnChanges(changes) { if (changes.points) { this.convert(); } if (changes.width || changes.height) { this.convert(); } } transform(p) { const dHeight = (this.height - this.diagramBottomPadding); return new Point2D((p.x - this.xMinMax.min) * this.sx * (this.width - 2 * this.padding) / this.width + this.padding, (dHeight - (p.y - this.yMinMax.min) * this.sy) * (this.height - 2 * this.padding) / this.height + this.padding); } mouseToDiagram(p) { const width = +this.width; const height = +this.height; const dHeight = height - +this.diagramBottomPadding; const padding = +this.padding; return new Point2D((((p.x - padding) / this.sx) * width) / (width - padding * 2) + this.xMinMax.min, (dHeight - p.y + padding) / this.sy + this.yMinMax.min); } interpolate(x) { if (x < this.xMinMax.min && x > this.xMinMax.max) { return NaN; } const index = this.points.findIndex(pt => pt.x >= x) - 1; if (index === -1) { return this.points[0].y; } const fp = this.points[index]; const sp = this.points[index + 1]; const a = (sp.y - fp.y) / (sp.x - fp.x); const b = fp.y - a * fp.x; return a * x + b; } mouseMove(event) { if (this.interactive && !this.points) { return; } const element = this.element.nativeElement; const mousePos = { x: event.x - element.offsetLeft, y: event.y - element.offsetTop }; const converted = this.mouseToDiagram(mousePos); const original = this.points.reduce((p, c) => { p = (p && Math.abs(p.x - converted.x) < Math.abs(c.x - converted.x) && p) || c; return p; }); const hovered = this.transform(original); this.hover.emit({ converted: hovered, original }); } convert() { this.xMinMax = ElementaryMath.getMinMax(this.points.map(p => p.x)); this.yMinMax = ElementaryMath.getMinMax(this.points.map(p => p.y)); this.dx = (this.xMinMax.max - this.xMinMax.min) || 1; this.dy = (this.yMinMax.max - this.yMinMax.min) || 1; const dHeight = (this.height - this.diagramBottomPadding); this.sx = this.width / this.dx; this.sy = dHeight / this.dy; const points = this.points.map(p => new Point2D((p.x - this.xMinMax.min) * this.sx, dHeight - (p.y - this.yMinMax.min) * this.sy)); this.convertedLines = 'M' + points.map(p => p.toString(' ')).join(''); this.convertedShape = points.concat([ new Point2D((this.xMinMax.max - this.xMinMax.min) * this.sx, (this.yMinMax.max - this.yMinMax.min) * this.sy + this.diagramBottomPadding), new Point2D(0, (this.yMinMax.max - this.yMinMax.min) * this.sy + this.diagramBottomPadding) ]).map(p => p.toString()).join(''); this.recalculate.emit({ component: this }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: SimpleDiagram2DComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: SimpleDiagram2DComponent, isStandalone: false, selector: "obl-simple-diagram2-d", inputs: { points: "points", gradient: "gradient", gradientUnits: "gradientUnits", padding: "padding", diagramBottomPadding: "diagramBottomPadding", height: "height", width: "width", interactive: "interactive" }, outputs: { recalculate: "recalculate", hover: "hover" }, usesOnChanges: true, ngImport: i0, template: "<svg width=\"100%\" [attr.viewBox]=\"'0 0 ' + this.width + ' ' + this.height\" (mousemove)=\"mouseMove($event)\">\n <defs>\n @if (gradient) {\n <g\n obl-svg-linear-gradient\n [gradient]=\"gradient\"\n [name]=\"gradientId\"\n [gradientUnits]=\"gradientUnits\"\n ></g>\n }\n </defs>\n <g\n [attr.transform]=\"\n 'translate(' +\n padding +\n ',' +\n padding +\n ') scale(' +\n (width - padding * 2) / width +\n ', ' +\n (height - padding * 2) / height +\n ')'\n \"\n >\n <polygon\n [attr.points]=\"convertedShape\"\n [style.fill]=\"gradient ? 'URL(#' + gradientId + ')' : undefined\"\n ></polygon>\n <path [attr.d]=\"convertedLines\"></path>\n </g>\n <ng-content></ng-content>\n</svg>\n", styles: ["path{stroke:var(--obl-primary);stroke-width:var(--obl-simple-diagram-stroke-width, 2px);fill:none}polygon{fill:var(--obl-secondary)}:host{display:flex}\n"], dependencies: [{ kind: "component", type: i1.SvgLinearGradientComponent, selector: "g[obl-svg-linear-gradient]", inputs: ["gradient", "gradientUnits", "name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: SimpleDiagram2DComponent, decorators: [{ type: Component, args: [{ selector: 'obl-simple-diagram2-d', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<svg width=\"100%\" [attr.viewBox]=\"'0 0 ' + this.width + ' ' + this.height\" (mousemove)=\"mouseMove($event)\">\n <defs>\n @if (gradient) {\n <g\n obl-svg-linear-gradient\n [gradient]=\"gradient\"\n [name]=\"gradientId\"\n [gradientUnits]=\"gradientUnits\"\n ></g>\n }\n </defs>\n <g\n [attr.transform]=\"\n 'translate(' +\n padding +\n ',' +\n padding +\n ') scale(' +\n (width - padding * 2) / width +\n ', ' +\n (height - padding * 2) / height +\n ')'\n \"\n >\n <polygon\n [attr.points]=\"convertedShape\"\n [style.fill]=\"gradient ? 'URL(#' + gradientId + ')' : undefined\"\n ></polygon>\n <path [attr.d]=\"convertedLines\"></path>\n </g>\n <ng-content></ng-content>\n</svg>\n", styles: ["path{stroke:var(--obl-primary);stroke-width:var(--obl-simple-diagram-stroke-width, 2px);fill:none}polygon{fill:var(--obl-secondary)}:host{display:flex}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { points: [{ type: Input }], gradient: [{ type: Input }], gradientUnits: [{ type: Input }], padding: [{ type: Input }], diagramBottomPadding: [{ type: Input }], height: [{ type: Input }], width: [{ type: Input }], interactive: [{ type: Input }], recalculate: [{ type: Output }], hover: [{ type: Output }] } }); class SimpleDiagram2DModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: SimpleDiagram2DModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: SimpleDiagram2DModule, declarations: [SimpleDiagram2DComponent], imports: [CommonModule, SvgModule], exports: [SimpleDiagram2DComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: SimpleDiagram2DModule, imports: [CommonModule, SvgModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: SimpleDiagram2DModule, decorators: [{ type: NgModule, args: [{ declarations: [ SimpleDiagram2DComponent ], imports: [ CommonModule, SvgModule ], exports: [ SimpleDiagram2DComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { SimpleDiagram2DComponent, SimpleDiagram2DModule }; //# sourceMappingURL=obliczeniowo-elementary-simple-diagram2-d.mjs.map