20172 lines
896 KiB
JavaScript
20172 lines
896 KiB
JavaScript
import * as i0 from '@angular/core';
|
|
import { PLATFORM_ID, Component, ViewEncapsulation, Inject, Input, ViewChild, HostBinding, HostListener, Injectable, ChangeDetectionStrategy, EventEmitter, Output, Directive, NgModule, ContentChild } from '@angular/core';
|
|
import * as i2 from '@angular/common';
|
|
import { isPlatformBrowser, isPlatformServer, CommonModule } from '@angular/common';
|
|
import { __decorate } from 'tslib';
|
|
import { DomPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
|
|
import { fromEvent } from 'rxjs';
|
|
import { debounceTime } from 'rxjs/operators';
|
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
import { select } from 'd3-selection';
|
|
import { brushX } from 'd3-brush';
|
|
import { scaleTime, scaleLinear, scalePoint, scaleOrdinal, scaleQuantile, scaleBand } from 'd3-scale';
|
|
import { area, curveLinear, line, arc, lineRadial, curveCardinalClosed, pie } from 'd3-shape';
|
|
import { range, min, max, quantile } from 'd3-array';
|
|
import { interpolate } from 'd3-interpolate';
|
|
import { easeSinInOut } from 'd3-ease';
|
|
import rfdc from 'rfdc';
|
|
import { format } from 'd3-format';
|
|
import * as d3_color from 'd3-color';
|
|
import { treemap, stratify } from 'd3-hierarchy';
|
|
import { sankey, sankeyLeft, sankeyLinkHorizontal } from 'd3-sankey';
|
|
import { timeFormat } from 'd3-time-format';
|
|
|
|
/**
|
|
* Throttle a function
|
|
*
|
|
*/
|
|
function throttle(func, wait, options) {
|
|
options = options || {};
|
|
let context;
|
|
let args;
|
|
let result;
|
|
let timeout = null;
|
|
let previous = 0;
|
|
function later() {
|
|
previous = options.leading === false ? 0 : +new Date();
|
|
timeout = null;
|
|
result = func.apply(context, args);
|
|
}
|
|
return function () {
|
|
const now = +new Date();
|
|
if (!previous && options.leading === false) {
|
|
previous = now;
|
|
}
|
|
const remaining = wait - (now - previous);
|
|
context = this;
|
|
// eslint-disable-next-line prefer-rest-params
|
|
args = arguments;
|
|
if (remaining <= 0) {
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
previous = now;
|
|
result = func.apply(context, args);
|
|
}
|
|
else if (!timeout && options.trailing !== false) {
|
|
timeout = setTimeout(later, remaining);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
/**
|
|
* Throttle decorator
|
|
*
|
|
* class MyClass {
|
|
* throttleable(10)
|
|
* myFn() { ... }
|
|
* }
|
|
*/
|
|
function throttleable(duration, options) {
|
|
return function innerDecorator(target, key, descriptor) {
|
|
return {
|
|
configurable: true,
|
|
enumerable: descriptor.enumerable,
|
|
get: function getter() {
|
|
Object.defineProperty(this, key, {
|
|
configurable: true,
|
|
enumerable: descriptor.enumerable,
|
|
value: throttle(descriptor.value, duration, options)
|
|
});
|
|
return this[key];
|
|
}
|
|
};
|
|
};
|
|
}
|
|
|
|
var PlacementTypes;
|
|
(function (PlacementTypes) {
|
|
PlacementTypes["Top"] = "top";
|
|
PlacementTypes["Bottom"] = "bottom";
|
|
PlacementTypes["Left"] = "left";
|
|
PlacementTypes["Right"] = "right";
|
|
PlacementTypes["Center"] = "center";
|
|
})(PlacementTypes || (PlacementTypes = {}));
|
|
|
|
const caretOffset = 7;
|
|
function verticalPosition(elDimensions, popoverDimensions, alignment) {
|
|
if (alignment === PlacementTypes.Top) {
|
|
return elDimensions.top - caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Bottom) {
|
|
return elDimensions.top + elDimensions.height - popoverDimensions.height + caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Center) {
|
|
return elDimensions.top + elDimensions.height / 2 - popoverDimensions.height / 2;
|
|
}
|
|
return undefined;
|
|
}
|
|
function horizontalPosition(elDimensions, popoverDimensions, alignment) {
|
|
if (alignment === PlacementTypes.Left) {
|
|
return elDimensions.left - caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Right) {
|
|
return elDimensions.left + elDimensions.width - popoverDimensions.width + caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Center) {
|
|
return elDimensions.left + elDimensions.width / 2 - popoverDimensions.width / 2;
|
|
}
|
|
return undefined;
|
|
}
|
|
/**
|
|
* Position helper for the popover directive.
|
|
*
|
|
* @export
|
|
*/
|
|
class PositionHelper {
|
|
/**
|
|
* Calculate vertical alignment position
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static calculateVerticalAlignment(elDimensions, popoverDimensions, alignment) {
|
|
let result = verticalPosition(elDimensions, popoverDimensions, alignment);
|
|
if (result + popoverDimensions.height > window.innerHeight) {
|
|
result = window.innerHeight - popoverDimensions.height;
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Calculate vertical caret position
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
|
|
let result;
|
|
if (alignment === PlacementTypes.Top) {
|
|
result = elDimensions.height / 2 - caretDimensions.height / 2 + caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Bottom) {
|
|
result = popoverDimensions.height - elDimensions.height / 2 - caretDimensions.height / 2 - caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Center) {
|
|
result = popoverDimensions.height / 2 - caretDimensions.height / 2;
|
|
}
|
|
const popoverPosition = verticalPosition(elDimensions, popoverDimensions, alignment);
|
|
if (popoverPosition + popoverDimensions.height > window.innerHeight) {
|
|
result += popoverPosition + popoverDimensions.height - window.innerHeight;
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Calculate horz alignment position
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static calculateHorizontalAlignment(elDimensions, popoverDimensions, alignment) {
|
|
let result = horizontalPosition(elDimensions, popoverDimensions, alignment);
|
|
if (result + popoverDimensions.width > window.innerWidth) {
|
|
result = window.innerWidth - popoverDimensions.width;
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Calculate horz caret position
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
|
|
let result;
|
|
if (alignment === PlacementTypes.Left) {
|
|
result = elDimensions.width / 2 - caretDimensions.width / 2 + caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Right) {
|
|
result = popoverDimensions.width - elDimensions.width / 2 - caretDimensions.width / 2 - caretOffset;
|
|
}
|
|
if (alignment === PlacementTypes.Center) {
|
|
result = popoverDimensions.width / 2 - caretDimensions.width / 2;
|
|
}
|
|
const popoverPosition = horizontalPosition(elDimensions, popoverDimensions, alignment);
|
|
if (popoverPosition + popoverDimensions.width > window.innerWidth) {
|
|
result += popoverPosition + popoverDimensions.width - window.innerWidth;
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Checks if the element's position should be flipped
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static shouldFlip(elDimensions, popoverDimensions, placement, spacing) {
|
|
let flip = false;
|
|
if (placement === PlacementTypes.Right) {
|
|
if (elDimensions.left + elDimensions.width + popoverDimensions.width + spacing > window.innerWidth) {
|
|
flip = true;
|
|
}
|
|
}
|
|
if (placement === PlacementTypes.Left) {
|
|
if (elDimensions.left - popoverDimensions.width - spacing < 0) {
|
|
flip = true;
|
|
}
|
|
}
|
|
if (placement === PlacementTypes.Top) {
|
|
if (elDimensions.top - popoverDimensions.height - spacing < 0) {
|
|
flip = true;
|
|
}
|
|
}
|
|
if (placement === PlacementTypes.Bottom) {
|
|
if (elDimensions.top + elDimensions.height + popoverDimensions.height + spacing > window.innerHeight) {
|
|
flip = true;
|
|
}
|
|
}
|
|
return flip;
|
|
}
|
|
/**
|
|
* Position caret
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static positionCaret(placement, elmDim, hostDim, caretDimensions, alignment) {
|
|
let top = 0;
|
|
let left = 0;
|
|
if (placement === PlacementTypes.Right) {
|
|
left = -7;
|
|
top = PositionHelper.calculateVerticalCaret(hostDim, elmDim, caretDimensions, alignment);
|
|
}
|
|
else if (placement === PlacementTypes.Left) {
|
|
left = elmDim.width;
|
|
top = PositionHelper.calculateVerticalCaret(hostDim, elmDim, caretDimensions, alignment);
|
|
}
|
|
else if (placement === PlacementTypes.Top) {
|
|
top = elmDim.height;
|
|
left = PositionHelper.calculateHorizontalCaret(hostDim, elmDim, caretDimensions, alignment);
|
|
}
|
|
else if (placement === PlacementTypes.Bottom) {
|
|
top = -7;
|
|
left = PositionHelper.calculateHorizontalCaret(hostDim, elmDim, caretDimensions, alignment);
|
|
}
|
|
return { top, left };
|
|
}
|
|
/**
|
|
* Position content
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static positionContent(placement, elmDim, hostDim, spacing, alignment) {
|
|
let top = 0;
|
|
let left = 0;
|
|
if (placement === PlacementTypes.Right) {
|
|
left = hostDim.left + hostDim.width + spacing;
|
|
top = PositionHelper.calculateVerticalAlignment(hostDim, elmDim, alignment);
|
|
}
|
|
else if (placement === PlacementTypes.Left) {
|
|
left = hostDim.left - elmDim.width - spacing;
|
|
top = PositionHelper.calculateVerticalAlignment(hostDim, elmDim, alignment);
|
|
}
|
|
else if (placement === PlacementTypes.Top) {
|
|
top = hostDim.top - elmDim.height - spacing;
|
|
left = PositionHelper.calculateHorizontalAlignment(hostDim, elmDim, alignment);
|
|
}
|
|
else if (placement === PlacementTypes.Bottom) {
|
|
top = hostDim.top + hostDim.height + spacing;
|
|
left = PositionHelper.calculateHorizontalAlignment(hostDim, elmDim, alignment);
|
|
}
|
|
return { top, left };
|
|
}
|
|
/**
|
|
* Determine placement based on flip
|
|
*
|
|
* @memberOf PositionHelper
|
|
*/
|
|
static determinePlacement(placement, elmDim, hostDim, spacing) {
|
|
const shouldFlip = PositionHelper.shouldFlip(hostDim, elmDim, placement, spacing);
|
|
if (shouldFlip) {
|
|
if (placement === PlacementTypes.Right) {
|
|
return PlacementTypes.Left;
|
|
}
|
|
else if (placement === PlacementTypes.Left) {
|
|
return PlacementTypes.Right;
|
|
}
|
|
else if (placement === PlacementTypes.Top) {
|
|
return PlacementTypes.Bottom;
|
|
}
|
|
else if (placement === PlacementTypes.Bottom) {
|
|
return PlacementTypes.Top;
|
|
}
|
|
}
|
|
return placement;
|
|
}
|
|
}
|
|
|
|
class TooltipContentComponent {
|
|
constructor(element, renderer, platformId) {
|
|
this.element = element;
|
|
this.renderer = renderer;
|
|
this.platformId = platformId;
|
|
}
|
|
get cssClasses() {
|
|
let clz = 'ngx-charts-tooltip-content';
|
|
clz += ` position-${this.placement}`;
|
|
clz += ` type-${this.type}`;
|
|
clz += ` ${this.cssClass}`;
|
|
return clz;
|
|
}
|
|
ngAfterViewInit() {
|
|
setTimeout(this.position.bind(this));
|
|
}
|
|
position() {
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
return;
|
|
}
|
|
const nativeElm = this.element.nativeElement;
|
|
const hostDim = this.host.nativeElement.getBoundingClientRect();
|
|
// if no dims were found, never show
|
|
if (!hostDim.height && !hostDim.width)
|
|
return;
|
|
const elmDim = nativeElm.getBoundingClientRect();
|
|
this.checkFlip(hostDim, elmDim);
|
|
this.positionContent(nativeElm, hostDim, elmDim);
|
|
if (this.showCaret) {
|
|
this.positionCaret(hostDim, elmDim);
|
|
}
|
|
// animate its entry
|
|
setTimeout(() => this.renderer.addClass(nativeElm, 'animate'), 1);
|
|
}
|
|
positionContent(nativeElm, hostDim, elmDim) {
|
|
const { top, left } = PositionHelper.positionContent(this.placement, elmDim, hostDim, this.spacing, this.alignment);
|
|
this.renderer.setStyle(nativeElm, 'top', `${top}px`);
|
|
this.renderer.setStyle(nativeElm, 'left', `${left}px`);
|
|
}
|
|
positionCaret(hostDim, elmDim) {
|
|
const caretElm = this.caretElm.nativeElement;
|
|
const caretDimensions = caretElm.getBoundingClientRect();
|
|
const { top, left } = PositionHelper.positionCaret(this.placement, elmDim, hostDim, caretDimensions, this.alignment);
|
|
this.renderer.setStyle(caretElm, 'top', `${top}px`);
|
|
this.renderer.setStyle(caretElm, 'left', `${left}px`);
|
|
}
|
|
checkFlip(hostDim, elmDim) {
|
|
this.placement = PositionHelper.determinePlacement(this.placement, elmDim, hostDim, this.spacing);
|
|
}
|
|
onWindowResize() {
|
|
this.position();
|
|
}
|
|
}
|
|
TooltipContentComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipContentComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
TooltipContentComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: TooltipContentComponent, selector: "ngx-tooltip-content", inputs: { host: "host", showCaret: "showCaret", type: "type", placement: "placement", alignment: "alignment", spacing: "spacing", cssClass: "cssClass", title: "title", template: "template", context: "context" }, host: { listeners: { "window:resize": "onWindowResize()" }, properties: { "class": "this.cssClasses" } }, viewQueries: [{ propertyName: "caretElm", first: true, predicate: ["caretElm"], descendants: true }], ngImport: i0, template: `
|
|
<div>
|
|
<span #caretElm [hidden]="!showCaret" class="tooltip-caret position-{{ this.placement }}"> </span>
|
|
<div class="tooltip-content">
|
|
<span *ngIf="!title">
|
|
<ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ model: context }"> </ng-template>
|
|
</span>
|
|
<span *ngIf="title" [innerHTML]="title"> </span>
|
|
</div>
|
|
</div>
|
|
`, isInline: true, styles: [".ngx-charts-tooltip-content{position:fixed;border-radius:3px;z-index:5000;display:block;font-weight:400;opacity:0;pointer-events:none!important}.ngx-charts-tooltip-content.type-popover{background:#fff;color:#060709;border:1px solid #72809b;box-shadow:0 1px 3px #0003,0 1px 1px #00000024,0 2px 1px -1px #0000001f;font-size:13px;padding:4px}.ngx-charts-tooltip-content.type-popover .tooltip-caret{position:absolute;z-index:5001;width:0;height:0}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-left{border-top:7px solid transparent;border-bottom:7px solid transparent;border-left:7px solid #fff}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-top{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #fff}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-right{border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid #fff}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-bottom{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #fff}.ngx-charts-tooltip-content.type-tooltip{color:#fff;background:rgba(0,0,0,.75);font-size:12px;padding:0 10px;text-align:center;pointer-events:auto}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-left{border-top:7px solid transparent;border-bottom:7px solid transparent;border-left:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-top{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-right{border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-bottom{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content .tooltip-label{display:block;line-height:1em;padding:8px 5px 5px;font-size:1em}.ngx-charts-tooltip-content .tooltip-val{display:block;font-size:1.3em;line-height:1em;padding:0 5px 8px}.ngx-charts-tooltip-content .tooltip-caret{position:absolute;z-index:5001;width:0;height:0}.ngx-charts-tooltip-content.position-right{transform:translate(10px)}.ngx-charts-tooltip-content.position-left{transform:translate(-10px)}.ngx-charts-tooltip-content.position-top{transform:translateY(-10px)}.ngx-charts-tooltip-content.position-bottom{transform:translateY(10px)}.ngx-charts-tooltip-content.animate{opacity:1;transition:opacity .3s,transform .3s;transform:translate(0);pointer-events:auto}.area-tooltip-container{padding:5px 0;pointer-events:none}.tooltip-item{text-align:left;line-height:1.2em;padding:5px 0}.tooltip-item .tooltip-item-color{display:inline-block;height:12px;width:12px;margin-right:5px;color:#5b646b;border-radius:3px}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
__decorate([
|
|
throttleable(100)
|
|
], TooltipContentComponent.prototype, "onWindowResize", null);
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipContentComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-tooltip-content', template: `
|
|
<div>
|
|
<span #caretElm [hidden]="!showCaret" class="tooltip-caret position-{{ this.placement }}"> </span>
|
|
<div class="tooltip-content">
|
|
<span *ngIf="!title">
|
|
<ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ model: context }"> </ng-template>
|
|
</span>
|
|
<span *ngIf="title" [innerHTML]="title"> </span>
|
|
</div>
|
|
</div>
|
|
`, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-tooltip-content{position:fixed;border-radius:3px;z-index:5000;display:block;font-weight:400;opacity:0;pointer-events:none!important}.ngx-charts-tooltip-content.type-popover{background:#fff;color:#060709;border:1px solid #72809b;box-shadow:0 1px 3px #0003,0 1px 1px #00000024,0 2px 1px -1px #0000001f;font-size:13px;padding:4px}.ngx-charts-tooltip-content.type-popover .tooltip-caret{position:absolute;z-index:5001;width:0;height:0}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-left{border-top:7px solid transparent;border-bottom:7px solid transparent;border-left:7px solid #fff}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-top{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #fff}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-right{border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid #fff}.ngx-charts-tooltip-content.type-popover .tooltip-caret.position-bottom{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #fff}.ngx-charts-tooltip-content.type-tooltip{color:#fff;background:rgba(0,0,0,.75);font-size:12px;padding:0 10px;text-align:center;pointer-events:auto}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-left{border-top:7px solid transparent;border-bottom:7px solid transparent;border-left:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-top{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-right{border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content.type-tooltip .tooltip-caret.position-bottom{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(0,0,0,.75)}.ngx-charts-tooltip-content .tooltip-label{display:block;line-height:1em;padding:8px 5px 5px;font-size:1em}.ngx-charts-tooltip-content .tooltip-val{display:block;font-size:1.3em;line-height:1em;padding:0 5px 8px}.ngx-charts-tooltip-content .tooltip-caret{position:absolute;z-index:5001;width:0;height:0}.ngx-charts-tooltip-content.position-right{transform:translate(10px)}.ngx-charts-tooltip-content.position-left{transform:translate(-10px)}.ngx-charts-tooltip-content.position-top{transform:translateY(-10px)}.ngx-charts-tooltip-content.position-bottom{transform:translateY(10px)}.ngx-charts-tooltip-content.animate{opacity:1;transition:opacity .3s,transform .3s;transform:translate(0);pointer-events:auto}.area-tooltip-container{padding:5px 0;pointer-events:none}.tooltip-item{text-align:left;line-height:1.2em;padding:5px 0}.tooltip-item .tooltip-item-color{display:inline-block;height:12px;width:12px;margin-right:5px;color:#5b646b;border-radius:3px}\n"] }]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { host: [{
|
|
type: Input
|
|
}], showCaret: [{
|
|
type: Input
|
|
}], type: [{
|
|
type: Input
|
|
}], placement: [{
|
|
type: Input
|
|
}], alignment: [{
|
|
type: Input
|
|
}], spacing: [{
|
|
type: Input
|
|
}], cssClass: [{
|
|
type: Input
|
|
}], title: [{
|
|
type: Input
|
|
}], template: [{
|
|
type: Input
|
|
}], context: [{
|
|
type: Input
|
|
}], caretElm: [{
|
|
type: ViewChild,
|
|
args: ['caretElm']
|
|
}], cssClasses: [{
|
|
type: HostBinding,
|
|
args: ['class']
|
|
}], onWindowResize: [{
|
|
type: HostListener,
|
|
args: ['window:resize']
|
|
}] } });
|
|
|
|
class InjectionRegisteryService {
|
|
constructor(injectionService) {
|
|
this.injectionService = injectionService;
|
|
this.defaults = {};
|
|
this.components = new Map();
|
|
}
|
|
getByType(type = this.type) {
|
|
return this.components.get(type);
|
|
}
|
|
create(bindings) {
|
|
return this.createByType(this.type, bindings);
|
|
}
|
|
createByType(type, bindings) {
|
|
bindings = this.assignDefaults(bindings);
|
|
const component = this.injectComponent(type, bindings);
|
|
this.register(type, component);
|
|
return component;
|
|
}
|
|
destroy(instance) {
|
|
const compsByType = this.components.get(instance.componentType);
|
|
if (compsByType && compsByType.length) {
|
|
const idx = compsByType.indexOf(instance);
|
|
if (idx > -1) {
|
|
const component = compsByType[idx];
|
|
component.destroy();
|
|
compsByType.splice(idx, 1);
|
|
}
|
|
}
|
|
}
|
|
destroyAll() {
|
|
this.destroyByType(this.type);
|
|
}
|
|
destroyByType(type) {
|
|
const comps = this.components.get(type);
|
|
if (comps && comps.length) {
|
|
let i = comps.length - 1;
|
|
while (i >= 0) {
|
|
this.destroy(comps[i--]);
|
|
}
|
|
}
|
|
}
|
|
injectComponent(type, bindings) {
|
|
return this.injectionService.appendComponent(type, bindings);
|
|
}
|
|
assignDefaults(bindings) {
|
|
const inputs = { ...this.defaults.inputs };
|
|
const outputs = { ...this.defaults.outputs };
|
|
if (!bindings.inputs && !bindings.outputs) {
|
|
bindings = { inputs: bindings };
|
|
}
|
|
if (inputs) {
|
|
bindings.inputs = { ...inputs, ...bindings.inputs };
|
|
}
|
|
if (outputs) {
|
|
bindings.outputs = { ...outputs, ...bindings.outputs };
|
|
}
|
|
return bindings;
|
|
}
|
|
register(type, component) {
|
|
if (!this.components.has(type)) {
|
|
this.components.set(type, []);
|
|
}
|
|
const types = this.components.get(type);
|
|
types.push(component);
|
|
}
|
|
}
|
|
|
|
function isViewContainerRef(x) {
|
|
return x.element;
|
|
}
|
|
/**
|
|
* Injection service is a helper to append components
|
|
* dynamically to a known location in the DOM, most
|
|
* noteably for dialogs/tooltips appending to body.
|
|
*
|
|
* @export
|
|
*/
|
|
class InjectionService {
|
|
constructor(applicationRef, componentFactoryResolver, injector) {
|
|
this.applicationRef = applicationRef;
|
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
this.injector = injector;
|
|
}
|
|
/**
|
|
* Sets a default global root view container. This is useful for
|
|
* things like ngUpgrade that doesn't have a ApplicationRef root.
|
|
*
|
|
* @param container
|
|
*/
|
|
static setGlobalRootViewContainer(container) {
|
|
InjectionService.globalRootViewContainer = container;
|
|
}
|
|
/**
|
|
* Gets the root view container to inject the component to.
|
|
*
|
|
* @memberOf InjectionService
|
|
*/
|
|
getRootViewContainer() {
|
|
if (this._container)
|
|
return this._container;
|
|
if (InjectionService.globalRootViewContainer)
|
|
return InjectionService.globalRootViewContainer;
|
|
if (this.applicationRef.components.length)
|
|
return this.applicationRef.components[0];
|
|
throw new Error('View Container not found! ngUpgrade needs to manually set this via setRootViewContainer or setGlobalRootViewContainer.');
|
|
}
|
|
/**
|
|
* Overrides the default root view container. This is useful for
|
|
* things like ngUpgrade that doesn't have a ApplicationRef root.
|
|
*
|
|
* @param container
|
|
*
|
|
* @memberOf InjectionService
|
|
*/
|
|
setRootViewContainer(container) {
|
|
this._container = container;
|
|
}
|
|
/**
|
|
* Gets the html element for a component ref.
|
|
*
|
|
* @param componentRef
|
|
*
|
|
* @memberOf InjectionService
|
|
*/
|
|
getComponentRootNode(component) {
|
|
if (isViewContainerRef(component)) {
|
|
return component.element.nativeElement;
|
|
}
|
|
if (component.hostView && component.hostView.rootNodes.length > 0) {
|
|
return component.hostView.rootNodes[0];
|
|
}
|
|
// the top most component root node has no `hostView`
|
|
return component.location.nativeElement;
|
|
}
|
|
/**
|
|
* Gets the root component container html element.
|
|
*
|
|
* @memberOf InjectionService
|
|
*/
|
|
getRootViewContainerNode(component) {
|
|
return this.getComponentRootNode(component);
|
|
}
|
|
/**
|
|
* Projects the bindings onto the component
|
|
*
|
|
* @param component
|
|
* @param options
|
|
*
|
|
* @memberOf InjectionService
|
|
*/
|
|
projectComponentBindings(component, bindings) {
|
|
if (bindings) {
|
|
if (bindings.inputs !== undefined) {
|
|
const bindingKeys = Object.getOwnPropertyNames(bindings.inputs);
|
|
for (const bindingName of bindingKeys) {
|
|
component.instance[bindingName] = bindings.inputs[bindingName];
|
|
}
|
|
}
|
|
if (bindings.outputs !== undefined) {
|
|
const eventKeys = Object.getOwnPropertyNames(bindings.outputs);
|
|
for (const eventName of eventKeys) {
|
|
component.instance[eventName] = bindings.outputs[eventName];
|
|
}
|
|
}
|
|
}
|
|
return component;
|
|
}
|
|
/**
|
|
* Appends a component to a adjacent location
|
|
*
|
|
* @param componentClass
|
|
* @param [options={}]
|
|
* @param [location]
|
|
*
|
|
* @memberOf InjectionService
|
|
*/
|
|
appendComponent(componentClass, bindings = {}, location) {
|
|
if (!location)
|
|
location = this.getRootViewContainer();
|
|
const appendLocation = this.getComponentRootNode(location);
|
|
const portalHost = new DomPortalOutlet(appendLocation, this.componentFactoryResolver, this.applicationRef, this.injector);
|
|
const portal = new ComponentPortal(componentClass);
|
|
const componentRef = portalHost.attach(portal);
|
|
this.projectComponentBindings(componentRef, bindings);
|
|
return componentRef;
|
|
}
|
|
}
|
|
InjectionService.globalRootViewContainer = null;
|
|
InjectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: InjectionService, deps: [{ token: i0.ApplicationRef }, { token: i0.ComponentFactoryResolver }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
InjectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: InjectionService });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: InjectionService, decorators: [{
|
|
type: Injectable
|
|
}], ctorParameters: function () { return [{ type: i0.ApplicationRef }, { type: i0.ComponentFactoryResolver }, { type: i0.Injector }]; } });
|
|
|
|
class TooltipService extends InjectionRegisteryService {
|
|
constructor(injectionService) {
|
|
super(injectionService);
|
|
this.type = TooltipContentComponent;
|
|
}
|
|
}
|
|
TooltipService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipService, deps: [{ token: InjectionService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
TooltipService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipService });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipService, decorators: [{
|
|
type: Injectable
|
|
}], ctorParameters: function () { return [{ type: InjectionService }]; } });
|
|
|
|
var LegendPosition;
|
|
(function (LegendPosition) {
|
|
LegendPosition["Right"] = "right";
|
|
LegendPosition["Below"] = "below";
|
|
})(LegendPosition || (LegendPosition = {}));
|
|
var LegendType;
|
|
(function (LegendType) {
|
|
LegendType["ScaleLegend"] = "scaleLegend";
|
|
LegendType["Legend"] = "legend";
|
|
})(LegendType || (LegendType = {}));
|
|
|
|
var ScaleType;
|
|
(function (ScaleType) {
|
|
ScaleType["Time"] = "time";
|
|
ScaleType["Linear"] = "linear";
|
|
ScaleType["Ordinal"] = "ordinal";
|
|
ScaleType["Quantile"] = "quantile";
|
|
})(ScaleType || (ScaleType = {}));
|
|
|
|
class ScaleLegendComponent {
|
|
constructor() {
|
|
this.horizontal = false;
|
|
}
|
|
ngOnChanges(changes) {
|
|
const gradientValues = this.gradientString(this.colors.range(), this.colors.domain());
|
|
const direction = this.horizontal ? 'right' : 'bottom';
|
|
this.gradient = `linear-gradient(to ${direction}, ${gradientValues})`;
|
|
}
|
|
/**
|
|
* Generates the string used in the gradient stylesheet properties
|
|
* @param colors array of colors
|
|
* @param splits array of splits on a scale of (0, 1)
|
|
*/
|
|
gradientString(colors, splits) {
|
|
// add the 100%
|
|
splits.push(1);
|
|
const pairs = [];
|
|
colors.reverse().forEach((c, i) => {
|
|
pairs.push(`${c} ${Math.round(splits[i] * 100)}%`);
|
|
});
|
|
return pairs.join(', ');
|
|
}
|
|
}
|
|
ScaleLegendComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ScaleLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
ScaleLegendComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: ScaleLegendComponent, selector: "ngx-charts-scale-legend", inputs: { valueRange: "valueRange", colors: "colors", height: "height", width: "width", horizontal: "horizontal" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<div
|
|
class="scale-legend"
|
|
[class.horizontal-legend]="horizontal"
|
|
[style.height.px]="horizontal ? undefined : height"
|
|
[style.width.px]="width"
|
|
>
|
|
<div class="scale-legend-label">
|
|
<span>{{ valueRange[1].toLocaleString() }}</span>
|
|
</div>
|
|
<div class="scale-legend-wrap" [style.background]="gradient"></div>
|
|
<div class="scale-legend-label">
|
|
<span>{{ valueRange[0].toLocaleString() }}</span>
|
|
</div>
|
|
</div>
|
|
`, isInline: true, styles: [".chart-legend{display:inline-block;padding:0;width:auto!important}.chart-legend .scale-legend{text-align:center;display:flex;flex-direction:column}.chart-legend .scale-legend-wrap{display:inline-block;flex:1;width:30px;border-radius:5px;margin:0 auto}.chart-legend .scale-legend-label{font-size:12px}.chart-legend .horizontal-legend.scale-legend{flex-direction:row}.chart-legend .horizontal-legend .scale-legend-wrap{width:auto;height:30px;margin:0 16px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ScaleLegendComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-scale-legend', template: `
|
|
<div
|
|
class="scale-legend"
|
|
[class.horizontal-legend]="horizontal"
|
|
[style.height.px]="horizontal ? undefined : height"
|
|
[style.width.px]="width"
|
|
>
|
|
<div class="scale-legend-label">
|
|
<span>{{ valueRange[1].toLocaleString() }}</span>
|
|
</div>
|
|
<div class="scale-legend-wrap" [style.background]="gradient"></div>
|
|
<div class="scale-legend-label">
|
|
<span>{{ valueRange[0].toLocaleString() }}</span>
|
|
</div>
|
|
</div>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".chart-legend{display:inline-block;padding:0;width:auto!important}.chart-legend .scale-legend{text-align:center;display:flex;flex-direction:column}.chart-legend .scale-legend-wrap{display:inline-block;flex:1;width:30px;border-radius:5px;margin:0 auto}.chart-legend .scale-legend-label{font-size:12px}.chart-legend .horizontal-legend.scale-legend{flex-direction:row}.chart-legend .horizontal-legend .scale-legend-wrap{width:auto;height:30px;margin:0 16px}\n"] }]
|
|
}], propDecorators: { valueRange: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], horizontal: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
/**
|
|
* Formats a label given a date, number or string.
|
|
*
|
|
* @export
|
|
*/
|
|
function formatLabel(label) {
|
|
if (label instanceof Date) {
|
|
label = label.toLocaleDateString();
|
|
}
|
|
else {
|
|
label = label.toLocaleString();
|
|
}
|
|
return label;
|
|
}
|
|
/**
|
|
* Escapes a label.
|
|
*
|
|
* @export
|
|
*/
|
|
function escapeLabel(label) {
|
|
return label.toLocaleString().replace(/[&'`"<>]/g, match => {
|
|
return {
|
|
'&': '&',
|
|
// tslint:disable-next-line: quotemark
|
|
"'": ''',
|
|
'`': '`',
|
|
'"': '"',
|
|
'<': '<',
|
|
'>': '>'
|
|
}[match];
|
|
});
|
|
}
|
|
|
|
class LegendEntryComponent {
|
|
constructor() {
|
|
this.isActive = false;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.toggle = new EventEmitter();
|
|
}
|
|
get trimmedLabel() {
|
|
return this.formattedLabel || '(empty)';
|
|
}
|
|
onMouseEnter() {
|
|
this.activate.emit({ name: this.label });
|
|
}
|
|
onMouseLeave() {
|
|
this.deactivate.emit({ name: this.label });
|
|
}
|
|
}
|
|
LegendEntryComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LegendEntryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
LegendEntryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LegendEntryComponent, selector: "ngx-charts-legend-entry", inputs: { color: "color", label: "label", formattedLabel: "formattedLabel", isActive: "isActive" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate", toggle: "toggle" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0, template: `
|
|
<span [title]="formattedLabel" tabindex="-1" [class.active]="isActive" (click)="select.emit(formattedLabel)">
|
|
<span class="legend-label-color" [style.background-color]="color" (click)="toggle.emit(formattedLabel)"> </span>
|
|
<span class="legend-label-text">
|
|
{{ trimmedLabel }}
|
|
</span>
|
|
</span>
|
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LegendEntryComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'ngx-charts-legend-entry',
|
|
template: `
|
|
<span [title]="formattedLabel" tabindex="-1" [class.active]="isActive" (click)="select.emit(formattedLabel)">
|
|
<span class="legend-label-color" [style.background-color]="color" (click)="toggle.emit(formattedLabel)"> </span>
|
|
<span class="legend-label-text">
|
|
{{ trimmedLabel }}
|
|
</span>
|
|
</span>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { color: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], formattedLabel: [{
|
|
type: Input
|
|
}], isActive: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], toggle: [{
|
|
type: Output
|
|
}], onMouseEnter: [{
|
|
type: HostListener,
|
|
args: ['mouseenter']
|
|
}], onMouseLeave: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class LegendComponent {
|
|
constructor(cd) {
|
|
this.cd = cd;
|
|
this.horizontal = false;
|
|
this.labelClick = new EventEmitter();
|
|
this.labelActivate = new EventEmitter();
|
|
this.labelDeactivate = new EventEmitter();
|
|
this.legendEntries = [];
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.cd.markForCheck();
|
|
this.legendEntries = this.getLegendEntries();
|
|
}
|
|
getLegendEntries() {
|
|
const items = [];
|
|
for (const label of this.data) {
|
|
const formattedLabel = formatLabel(label);
|
|
const idx = items.findIndex(i => {
|
|
return i.label === formattedLabel;
|
|
});
|
|
if (idx === -1) {
|
|
items.push({
|
|
label,
|
|
formattedLabel,
|
|
color: this.colors.getColor(label)
|
|
});
|
|
}
|
|
}
|
|
return items;
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.label === d.name;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
activate(item) {
|
|
this.labelActivate.emit(item);
|
|
}
|
|
deactivate(item) {
|
|
this.labelDeactivate.emit(item);
|
|
}
|
|
trackBy(index, item) {
|
|
return item.label;
|
|
}
|
|
}
|
|
LegendComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LegendComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
LegendComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LegendComponent, selector: "ngx-charts-legend", inputs: { data: "data", title: "title", colors: "colors", height: "height", width: "width", activeEntries: "activeEntries", horizontal: "horizontal" }, outputs: { labelClick: "labelClick", labelActivate: "labelActivate", labelDeactivate: "labelDeactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<div [style.width.px]="width">
|
|
<header class="legend-title" *ngIf="title?.length > 0">
|
|
<span class="legend-title-text">{{ title }}</span>
|
|
</header>
|
|
<div class="legend-wrap">
|
|
<ul class="legend-labels" [class.horizontal-legend]="horizontal" [style.max-height.px]="height - 45">
|
|
<li *ngFor="let entry of legendEntries; trackBy: trackBy" class="legend-label">
|
|
<ngx-charts-legend-entry
|
|
[label]="entry.label"
|
|
[formattedLabel]="entry.formattedLabel"
|
|
[color]="entry.color"
|
|
[isActive]="isActive(entry)"
|
|
(select)="labelClick.emit($event)"
|
|
(activate)="activate($event)"
|
|
(deactivate)="deactivate($event)"
|
|
>
|
|
</ngx-charts-legend-entry>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
`, isInline: true, styles: [".chart-legend{display:inline-block;padding:0;width:auto!important}.chart-legend .legend-title{white-space:nowrap;overflow:hidden;margin-left:10px;margin-bottom:5px;font-size:14px;font-weight:700}.chart-legend ul,.chart-legend li{padding:0;margin:0;list-style:none}.chart-legend .horizontal-legend li{display:inline-block}.chart-legend .legend-wrap{width:calc(100% - 10px)}.chart-legend .legend-labels{line-height:85%;list-style:none;text-align:left;float:left;width:100%;border-radius:3px;overflow-y:auto;overflow-x:hidden;white-space:nowrap;background:rgba(0,0,0,.05)}.chart-legend .legend-label{cursor:pointer;font-size:90%;margin:8px;color:#afb7c8}.chart-legend .legend-label:hover{color:#000;transition:.2s}.chart-legend .legend-label .active .legend-label-text{color:#000}.chart-legend .legend-label-color{display:inline-block;height:15px;width:15px;margin-right:5px;color:#5b646b;border-radius:3px}.chart-legend .legend-label-text{display:inline-block;vertical-align:top;line-height:15px;font-size:12px;width:calc(100% - 20px);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.chart-legend .legend-title-text{vertical-align:bottom;display:inline-block;line-height:16px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n"], components: [{ type: LegendEntryComponent, selector: "ngx-charts-legend-entry", inputs: ["color", "label", "formattedLabel", "isActive"], outputs: ["select", "activate", "deactivate", "toggle"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LegendComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-legend', template: `
|
|
<div [style.width.px]="width">
|
|
<header class="legend-title" *ngIf="title?.length > 0">
|
|
<span class="legend-title-text">{{ title }}</span>
|
|
</header>
|
|
<div class="legend-wrap">
|
|
<ul class="legend-labels" [class.horizontal-legend]="horizontal" [style.max-height.px]="height - 45">
|
|
<li *ngFor="let entry of legendEntries; trackBy: trackBy" class="legend-label">
|
|
<ngx-charts-legend-entry
|
|
[label]="entry.label"
|
|
[formattedLabel]="entry.formattedLabel"
|
|
[color]="entry.color"
|
|
[isActive]="isActive(entry)"
|
|
(select)="labelClick.emit($event)"
|
|
(activate)="activate($event)"
|
|
(deactivate)="deactivate($event)"
|
|
>
|
|
</ngx-charts-legend-entry>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".chart-legend{display:inline-block;padding:0;width:auto!important}.chart-legend .legend-title{white-space:nowrap;overflow:hidden;margin-left:10px;margin-bottom:5px;font-size:14px;font-weight:700}.chart-legend ul,.chart-legend li{padding:0;margin:0;list-style:none}.chart-legend .horizontal-legend li{display:inline-block}.chart-legend .legend-wrap{width:calc(100% - 10px)}.chart-legend .legend-labels{line-height:85%;list-style:none;text-align:left;float:left;width:100%;border-radius:3px;overflow-y:auto;overflow-x:hidden;white-space:nowrap;background:rgba(0,0,0,.05)}.chart-legend .legend-label{cursor:pointer;font-size:90%;margin:8px;color:#afb7c8}.chart-legend .legend-label:hover{color:#000;transition:.2s}.chart-legend .legend-label .active .legend-label-text{color:#000}.chart-legend .legend-label-color{display:inline-block;height:15px;width:15px;margin-right:5px;color:#5b646b;border-radius:3px}.chart-legend .legend-label-text{display:inline-block;vertical-align:top;line-height:15px;font-size:12px;width:calc(100% - 20px);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.chart-legend .legend-title-text{vertical-align:bottom;display:inline-block;line-height:16px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n"] }]
|
|
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { data: [{
|
|
type: Input
|
|
}], title: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], horizontal: [{
|
|
type: Input
|
|
}], labelClick: [{
|
|
type: Output
|
|
}], labelActivate: [{
|
|
type: Output
|
|
}], labelDeactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class ChartComponent {
|
|
constructor() {
|
|
this.showLegend = false;
|
|
this.animations = true;
|
|
this.legendLabelClick = new EventEmitter();
|
|
this.legendLabelActivate = new EventEmitter();
|
|
this.legendLabelDeactivate = new EventEmitter();
|
|
this.LegendPosition = LegendPosition;
|
|
this.LegendType = LegendType;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
let legendColumns = 0;
|
|
if (this.showLegend) {
|
|
this.legendType = this.getLegendType();
|
|
if (!this.legendOptions || this.legendOptions.position === LegendPosition.Right) {
|
|
if (this.legendType === LegendType.ScaleLegend) {
|
|
legendColumns = 1;
|
|
}
|
|
else {
|
|
legendColumns = 2;
|
|
}
|
|
}
|
|
}
|
|
const chartColumns = 12 - legendColumns;
|
|
this.chartWidth = Math.floor((this.view[0] * chartColumns) / 12.0);
|
|
this.legendWidth =
|
|
!this.legendOptions || this.legendOptions.position === LegendPosition.Right
|
|
? Math.floor((this.view[0] * legendColumns) / 12.0)
|
|
: this.chartWidth;
|
|
}
|
|
getLegendType() {
|
|
return this.legendOptions.scaleType === ScaleType.Linear ? LegendType.ScaleLegend : LegendType.Legend;
|
|
}
|
|
}
|
|
ChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
ChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: ChartComponent, selector: "ngx-charts-chart", inputs: { view: "view", showLegend: "showLegend", legendOptions: "legendOptions", legendType: "legendType", activeEntries: "activeEntries", animations: "animations" }, outputs: { legendLabelClick: "legendLabelClick", legendLabelActivate: "legendLabelActivate", legendLabelDeactivate: "legendLabelDeactivate" }, providers: [TooltipService], usesOnChanges: true, ngImport: i0, template: `
|
|
<div class="ngx-charts-outer" [style.width.px]="view[0]" [style.height.px]="view[1]">
|
|
<svg class="ngx-charts" [attr.width]="chartWidth" [attr.height]="view[1]">
|
|
<ng-content></ng-content>
|
|
</svg>
|
|
<ngx-charts-scale-legend
|
|
*ngIf="showLegend && legendType === LegendType.ScaleLegend"
|
|
class="chart-legend"
|
|
[horizontal]="legendOptions && legendOptions.position === LegendPosition.Below"
|
|
[valueRange]="legendOptions.domain"
|
|
[colors]="legendOptions.colors"
|
|
[height]="view[1]"
|
|
[width]="legendWidth"
|
|
>
|
|
</ngx-charts-scale-legend>
|
|
<ngx-charts-legend
|
|
*ngIf="showLegend && legendType === LegendType.Legend"
|
|
class="chart-legend"
|
|
[horizontal]="legendOptions && legendOptions.position === LegendPosition.Below"
|
|
[data]="legendOptions.domain"
|
|
[title]="legendOptions.title"
|
|
[colors]="legendOptions.colors"
|
|
[height]="view[1]"
|
|
[width]="legendWidth"
|
|
[activeEntries]="activeEntries"
|
|
(labelClick)="legendLabelClick.emit($event)"
|
|
(labelActivate)="legendLabelActivate.emit($event)"
|
|
(labelDeactivate)="legendLabelDeactivate.emit($event)"
|
|
>
|
|
</ngx-charts-legend>
|
|
</div>
|
|
`, isInline: true, components: [{ type: ScaleLegendComponent, selector: "ngx-charts-scale-legend", inputs: ["valueRange", "colors", "height", "width", "horizontal"] }, { type: LegendComponent, selector: "ngx-charts-legend", inputs: ["data", "title", "colors", "height", "width", "activeEntries", "horizontal"], outputs: ["labelClick", "labelActivate", "labelDeactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
providers: [TooltipService],
|
|
selector: 'ngx-charts-chart',
|
|
template: `
|
|
<div class="ngx-charts-outer" [style.width.px]="view[0]" [style.height.px]="view[1]">
|
|
<svg class="ngx-charts" [attr.width]="chartWidth" [attr.height]="view[1]">
|
|
<ng-content></ng-content>
|
|
</svg>
|
|
<ngx-charts-scale-legend
|
|
*ngIf="showLegend && legendType === LegendType.ScaleLegend"
|
|
class="chart-legend"
|
|
[horizontal]="legendOptions && legendOptions.position === LegendPosition.Below"
|
|
[valueRange]="legendOptions.domain"
|
|
[colors]="legendOptions.colors"
|
|
[height]="view[1]"
|
|
[width]="legendWidth"
|
|
>
|
|
</ngx-charts-scale-legend>
|
|
<ngx-charts-legend
|
|
*ngIf="showLegend && legendType === LegendType.Legend"
|
|
class="chart-legend"
|
|
[horizontal]="legendOptions && legendOptions.position === LegendPosition.Below"
|
|
[data]="legendOptions.domain"
|
|
[title]="legendOptions.title"
|
|
[colors]="legendOptions.colors"
|
|
[height]="view[1]"
|
|
[width]="legendWidth"
|
|
[activeEntries]="activeEntries"
|
|
(labelClick)="legendLabelClick.emit($event)"
|
|
(labelActivate)="legendLabelActivate.emit($event)"
|
|
(labelDeactivate)="legendLabelDeactivate.emit($event)"
|
|
>
|
|
</ngx-charts-legend>
|
|
</div>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { view: [{
|
|
type: Input
|
|
}], showLegend: [{
|
|
type: Input
|
|
}], legendOptions: [{
|
|
type: Input
|
|
}], legendType: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], legendLabelClick: [{
|
|
type: Output
|
|
}], legendLabelActivate: [{
|
|
type: Output
|
|
}], legendLabelDeactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
/**
|
|
* Visibility Observer
|
|
*/
|
|
class VisibilityObserver {
|
|
constructor(element, zone) {
|
|
this.element = element;
|
|
this.zone = zone;
|
|
this.visible = new EventEmitter();
|
|
this.isVisible = false;
|
|
this.runCheck();
|
|
}
|
|
destroy() {
|
|
clearTimeout(this.timeout);
|
|
}
|
|
onVisibilityChange() {
|
|
// trigger zone recalc for columns
|
|
this.zone.run(() => {
|
|
this.isVisible = true;
|
|
this.visible.emit(true);
|
|
});
|
|
}
|
|
runCheck() {
|
|
const check = () => {
|
|
if (!this.element) {
|
|
return;
|
|
}
|
|
// https://davidwalsh.name/offsetheight-visibility
|
|
const { offsetHeight, offsetWidth } = this.element.nativeElement;
|
|
if (offsetHeight && offsetWidth) {
|
|
clearTimeout(this.timeout);
|
|
this.onVisibilityChange();
|
|
}
|
|
else {
|
|
clearTimeout(this.timeout);
|
|
this.zone.runOutsideAngular(() => {
|
|
this.timeout = setTimeout(() => check(), 100);
|
|
});
|
|
}
|
|
};
|
|
this.zone.runOutsideAngular(() => {
|
|
this.timeout = setTimeout(() => check());
|
|
});
|
|
}
|
|
}
|
|
VisibilityObserver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: VisibilityObserver, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
|
|
VisibilityObserver.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.1.0", type: VisibilityObserver, selector: "visibility-observer", outputs: { visible: "visible" }, ngImport: i0 });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: VisibilityObserver, decorators: [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: 'visibility-observer'
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { visible: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
function isDate(value) {
|
|
return toString.call(value) === '[object Date]';
|
|
}
|
|
function isNumber(value) {
|
|
return typeof value === 'number';
|
|
}
|
|
|
|
class BaseChartComponent {
|
|
constructor(chartElement, zone, cd, platformId) {
|
|
this.chartElement = chartElement;
|
|
this.zone = zone;
|
|
this.cd = cd;
|
|
this.platformId = platformId;
|
|
this.scheme = 'cool';
|
|
this.schemeType = ScaleType.Ordinal;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.animations = false;
|
|
}
|
|
}
|
|
ngAfterViewInit() {
|
|
this.bindWindowResizeEvent();
|
|
// listen for visibility of the element for hidden by default scenario
|
|
this.visibilityObserver = new VisibilityObserver(this.chartElement, this.zone);
|
|
this.visibilityObserver.visible.subscribe(this.update.bind(this));
|
|
}
|
|
ngOnDestroy() {
|
|
this.unbindEvents();
|
|
if (this.visibilityObserver) {
|
|
this.visibilityObserver.visible.unsubscribe();
|
|
this.visibilityObserver.destroy();
|
|
}
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
if (this.results) {
|
|
this.results = this.cloneData(this.results);
|
|
}
|
|
else {
|
|
this.results = [];
|
|
}
|
|
if (this.view) {
|
|
this.width = this.view[0];
|
|
this.height = this.view[1];
|
|
}
|
|
else {
|
|
const dims = this.getContainerDims();
|
|
if (dims) {
|
|
this.width = dims.width;
|
|
this.height = dims.height;
|
|
}
|
|
}
|
|
// default values if width or height are 0 or undefined
|
|
if (!this.width) {
|
|
this.width = 600;
|
|
}
|
|
if (!this.height) {
|
|
this.height = 400;
|
|
}
|
|
this.width = Math.floor(this.width);
|
|
this.height = Math.floor(this.height);
|
|
if (this.cd) {
|
|
this.cd.markForCheck();
|
|
}
|
|
}
|
|
getContainerDims() {
|
|
let width;
|
|
let height;
|
|
const hostElem = this.chartElement.nativeElement;
|
|
if (isPlatformBrowser(this.platformId) && hostElem.parentNode !== null) {
|
|
// Get the container dimensions
|
|
const dims = hostElem.parentNode.getBoundingClientRect();
|
|
width = dims.width;
|
|
height = dims.height;
|
|
}
|
|
if (width && height) {
|
|
return { width, height };
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* Converts all date objects that appear as name
|
|
* into formatted date strings
|
|
*/
|
|
formatDates() {
|
|
for (let i = 0; i < this.results.length; i++) {
|
|
const g = this.results[i];
|
|
g.label = g.name;
|
|
if (isDate(g.label)) {
|
|
g.label = g.label.toLocaleDateString();
|
|
}
|
|
if (g.series) {
|
|
for (let j = 0; j < g.series.length; j++) {
|
|
const d = g.series[j];
|
|
d.label = d.name;
|
|
if (isDate(d.label)) {
|
|
d.label = d.label.toLocaleDateString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
unbindEvents() {
|
|
if (this.resizeSubscription) {
|
|
this.resizeSubscription.unsubscribe();
|
|
}
|
|
}
|
|
bindWindowResizeEvent() {
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
return;
|
|
}
|
|
const source = fromEvent(window, 'resize');
|
|
const subscription = source.pipe(debounceTime(200)).subscribe(e => {
|
|
this.update();
|
|
if (this.cd) {
|
|
this.cd.markForCheck();
|
|
}
|
|
});
|
|
this.resizeSubscription = subscription;
|
|
}
|
|
/**
|
|
* Clones the data into a new object
|
|
*
|
|
* @memberOf BaseChart
|
|
*/
|
|
cloneData(data) {
|
|
const results = [];
|
|
for (const item of data) {
|
|
const copy = {};
|
|
if (item['name'] !== undefined) {
|
|
copy['name'] = item['name'];
|
|
}
|
|
if (item['value'] !== undefined) {
|
|
copy['value'] = item['value'];
|
|
}
|
|
if (item['series'] !== undefined) {
|
|
copy['series'] = [];
|
|
for (const seriesItem of item['series']) {
|
|
const seriesItemCopy = Object.assign({}, seriesItem);
|
|
copy['series'].push(seriesItemCopy);
|
|
}
|
|
}
|
|
if (item['extra'] !== undefined) {
|
|
copy['extra'] = JSON.parse(JSON.stringify(item['extra']));
|
|
}
|
|
if (item['source'] !== undefined) {
|
|
copy['source'] = item['source'];
|
|
}
|
|
if (item['target'] !== undefined) {
|
|
copy['target'] = item['target'];
|
|
}
|
|
results.push(copy);
|
|
}
|
|
return results;
|
|
}
|
|
}
|
|
BaseChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BaseChartComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
BaseChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BaseChartComponent, selector: "base-chart", inputs: { results: "results", view: "view", scheme: "scheme", schemeType: "schemeType", customColors: "customColors", animations: "animations" }, outputs: { select: "select" }, usesOnChanges: true, ngImport: i0, template: ` <div></div> `, isInline: true });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BaseChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'base-chart',
|
|
template: ` <div></div> `
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { results: [{
|
|
type: Input
|
|
}], view: [{
|
|
type: Input
|
|
}], scheme: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], customColors: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
var Orientation;
|
|
(function (Orientation) {
|
|
Orientation["Top"] = "top";
|
|
Orientation["Bottom"] = "bottom";
|
|
Orientation["Left"] = "left";
|
|
Orientation["Right"] = "right";
|
|
})(Orientation || (Orientation = {}));
|
|
|
|
class AxisLabelComponent {
|
|
constructor(element) {
|
|
this.textHeight = 25;
|
|
this.margin = 5;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.strokeWidth = '0.01';
|
|
this.textAnchor = 'middle';
|
|
this.transform = '';
|
|
switch (this.orient) {
|
|
case Orientation.Top:
|
|
this.y = this.offset;
|
|
this.x = this.width / 2;
|
|
break;
|
|
case Orientation.Bottom:
|
|
this.y = this.offset;
|
|
this.x = this.width / 2;
|
|
break;
|
|
case Orientation.Left:
|
|
this.y = -(this.offset + this.textHeight + this.margin);
|
|
this.x = -this.height / 2;
|
|
this.transform = 'rotate(270)';
|
|
break;
|
|
case Orientation.Right:
|
|
this.y = this.offset + this.margin;
|
|
this.x = -this.height / 2;
|
|
this.transform = 'rotate(270)';
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
AxisLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AxisLabelComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
AxisLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AxisLabelComponent, selector: "g[ngx-charts-axis-label]", inputs: { orient: "orient", label: "label", offset: "offset", width: "width", height: "height" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:text
|
|
[attr.stroke-width]="strokeWidth"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
[attr.text-anchor]="textAnchor"
|
|
[attr.transform]="transform"
|
|
>
|
|
{{ label }}
|
|
</svg:text>
|
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AxisLabelComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-axis-label]',
|
|
template: `
|
|
<svg:text
|
|
[attr.stroke-width]="strokeWidth"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
[attr.text-anchor]="textAnchor"
|
|
[attr.transform]="transform"
|
|
>
|
|
{{ label }}
|
|
</svg:text>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { orient: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], offset: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
function trimLabel(s, max = 16) {
|
|
if (typeof s !== 'string') {
|
|
if (typeof s === 'number') {
|
|
return s + '';
|
|
}
|
|
else {
|
|
return '';
|
|
}
|
|
}
|
|
s = s.trim();
|
|
if (s.length <= max) {
|
|
return s;
|
|
}
|
|
else {
|
|
return `${s.slice(0, max)}...`;
|
|
}
|
|
}
|
|
|
|
function reduceTicks(ticks, maxTicks) {
|
|
if (ticks.length > maxTicks) {
|
|
const reduced = [];
|
|
const modulus = Math.floor(ticks.length / maxTicks);
|
|
for (let i = 0; i < ticks.length; i++) {
|
|
if (i % modulus === 0) {
|
|
reduced.push(ticks[i]);
|
|
}
|
|
}
|
|
ticks = reduced;
|
|
}
|
|
return ticks;
|
|
}
|
|
function getTickLines(label, maxLength, maxLines) {
|
|
const labelString = (label || '').toString();
|
|
let totalLines = [];
|
|
if (/\s/.test(labelString)) {
|
|
totalLines = labelString.split(/\s+/).reduce((lines, line) => {
|
|
const last = (lines.pop() || '') + ' ';
|
|
return last.length + line.length > maxLength ? [...lines, last.trim(), line.trim()] : [...lines, last + line];
|
|
}, []);
|
|
}
|
|
else {
|
|
let startIndex = 0;
|
|
while (startIndex < labelString.length) {
|
|
totalLines.push(labelString.substring(startIndex, startIndex + maxLength));
|
|
startIndex += maxLength;
|
|
}
|
|
}
|
|
if (totalLines.length > maxLines) {
|
|
totalLines = totalLines.splice(0, maxLines);
|
|
totalLines[totalLines.length - 1] += '...';
|
|
}
|
|
return totalLines;
|
|
}
|
|
|
|
var TextAnchor;
|
|
(function (TextAnchor) {
|
|
TextAnchor["Start"] = "start";
|
|
TextAnchor["Middle"] = "middle";
|
|
TextAnchor["End"] = "end";
|
|
})(TextAnchor || (TextAnchor = {}));
|
|
|
|
class XAxisTicksComponent {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.tickArguments = [5];
|
|
this.tickStroke = '#ccc';
|
|
this.trimTicks = true;
|
|
this.maxTickLength = 16;
|
|
this.showGridLines = false;
|
|
this.rotateTicks = true;
|
|
this.wrapTicks = false;
|
|
this.dimensionsChanged = new EventEmitter();
|
|
this.verticalSpacing = 20;
|
|
this.rotateLabels = false;
|
|
this.innerTickSize = 6;
|
|
this.outerTickSize = 6;
|
|
this.tickPadding = 3;
|
|
this.textAnchor = TextAnchor.Middle;
|
|
this.maxTicksLength = 0;
|
|
this.maxAllowedLength = 16;
|
|
this.height = 0;
|
|
this.approxHeight = 10;
|
|
this.maxPossibleLengthForTickIfWrapped = 16;
|
|
}
|
|
get isWrapTicksSupported() {
|
|
return this.wrapTicks && this.scale.step;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
ngAfterViewInit() {
|
|
setTimeout(() => this.updateDims());
|
|
}
|
|
updateDims() {
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
// for SSR, use approximate value instead of measured
|
|
this.dimensionsChanged.emit({ height: this.approxHeight });
|
|
return;
|
|
}
|
|
const height = parseInt(this.ticksElement.nativeElement.getBoundingClientRect().height, 10);
|
|
if (height !== this.height) {
|
|
this.height = height;
|
|
this.dimensionsChanged.emit({ height: this.height });
|
|
setTimeout(() => this.updateDims());
|
|
}
|
|
}
|
|
update() {
|
|
const scale = this.scale;
|
|
this.ticks = this.getTicks();
|
|
if (this.tickFormatting) {
|
|
this.tickFormat = this.tickFormatting;
|
|
}
|
|
else if (scale.tickFormat) {
|
|
// eslint-disable-next-line prefer-spread
|
|
this.tickFormat = scale.tickFormat.apply(scale, this.tickArguments);
|
|
}
|
|
else {
|
|
this.tickFormat = function (d) {
|
|
if (d.constructor.name === 'Date') {
|
|
return d.toLocaleDateString();
|
|
}
|
|
return d.toLocaleString();
|
|
};
|
|
}
|
|
const angle = this.rotateTicks ? this.getRotationAngle(this.ticks) : null;
|
|
this.adjustedScale = this.scale.bandwidth
|
|
? function (d) {
|
|
return this.scale(d) + this.scale.bandwidth() * 0.5;
|
|
}
|
|
: this.scale;
|
|
this.textTransform = '';
|
|
if (angle && angle !== 0) {
|
|
this.textTransform = `rotate(${angle})`;
|
|
this.textAnchor = TextAnchor.End;
|
|
this.verticalSpacing = 10;
|
|
}
|
|
else {
|
|
this.textAnchor = TextAnchor.Middle;
|
|
}
|
|
setTimeout(() => this.updateDims());
|
|
}
|
|
getRotationAngle(ticks) {
|
|
let angle = 0;
|
|
this.maxTicksLength = 0;
|
|
for (let i = 0; i < ticks.length; i++) {
|
|
const tick = this.tickFormat(ticks[i]).toString();
|
|
let tickLength = tick.length;
|
|
if (this.trimTicks) {
|
|
tickLength = this.tickTrim(tick).length;
|
|
}
|
|
if (tickLength > this.maxTicksLength) {
|
|
this.maxTicksLength = tickLength;
|
|
}
|
|
}
|
|
const len = Math.min(this.maxTicksLength, this.maxAllowedLength);
|
|
const charWidth = 7; // need to measure this
|
|
const wordWidth = len * charWidth;
|
|
let baseWidth = wordWidth;
|
|
const maxBaseWidth = Math.floor(this.width / ticks.length);
|
|
// calculate optimal angle
|
|
while (baseWidth > maxBaseWidth && angle > -90) {
|
|
angle -= 30;
|
|
baseWidth = Math.cos(angle * (Math.PI / 180)) * wordWidth;
|
|
}
|
|
let labelHeight = 14;
|
|
if (this.isWrapTicksSupported) {
|
|
const longestTick = this.ticks.reduce((earlier, current) => (current.length > earlier.length ? current : earlier), '');
|
|
const tickLines = this.tickChunks(longestTick);
|
|
labelHeight = 14 * (tickLines.length || 1);
|
|
this.maxPossibleLengthForTickIfWrapped = this.getMaxPossibleLengthForTick(longestTick);
|
|
}
|
|
const requiredHeight = angle !== 0
|
|
? Math.max(Math.abs(Math.sin((angle * Math.PI) / 180)) * this.maxTickLength * charWidth, 10)
|
|
: labelHeight;
|
|
this.approxHeight = Math.min(requiredHeight, 200);
|
|
return angle;
|
|
}
|
|
getTicks() {
|
|
let ticks;
|
|
const maxTicks = this.getMaxTicks(20);
|
|
const maxScaleTicks = this.getMaxTicks(100);
|
|
if (this.tickValues) {
|
|
ticks = this.tickValues;
|
|
}
|
|
else if (this.scale.ticks) {
|
|
ticks = this.scale.ticks.apply(this.scale, [maxScaleTicks]);
|
|
}
|
|
else {
|
|
ticks = this.scale.domain();
|
|
ticks = reduceTicks(ticks, maxTicks);
|
|
}
|
|
return ticks;
|
|
}
|
|
getMaxTicks(tickWidth) {
|
|
return Math.floor(this.width / tickWidth);
|
|
}
|
|
tickTransform(tick) {
|
|
return 'translate(' + this.adjustedScale(tick) + ',' + this.verticalSpacing + ')';
|
|
}
|
|
gridLineTransform() {
|
|
return `translate(0,${-this.verticalSpacing - 5})`;
|
|
}
|
|
tickTrim(label) {
|
|
return this.trimTicks ? trimLabel(label, this.maxTickLength) : label;
|
|
}
|
|
getMaxPossibleLengthForTick(longestLabel) {
|
|
if (this.scale.bandwidth) {
|
|
const averageCharacterWidth = 7; // approximate char width
|
|
const maxCharacters = Math.floor(this.scale.bandwidth() / averageCharacterWidth);
|
|
const truncatedText = longestLabel.slice(0, maxCharacters);
|
|
return Math.max(truncatedText.length, this.maxTickLength);
|
|
}
|
|
return this.maxTickLength;
|
|
}
|
|
tickChunks(label) {
|
|
if (label.toString().length > this.maxTickLength && this.scale.bandwidth) {
|
|
const maxAllowedLines = 5;
|
|
let maxLines = this.rotateTicks ? Math.floor(this.scale.step() / 14) : maxAllowedLines;
|
|
if (maxLines <= 1) {
|
|
return [this.tickTrim(label)];
|
|
}
|
|
let possibleStringLength = Math.max(this.maxPossibleLengthForTickIfWrapped, this.maxTickLength);
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
possibleStringLength = Math.floor(Math.min(this.approxHeight / maxAllowedLines, Math.max(this.maxPossibleLengthForTickIfWrapped, this.maxTickLength)));
|
|
}
|
|
maxLines = Math.min(maxLines, maxAllowedLines);
|
|
const lines = getTickLines(label, possibleStringLength, maxLines < 1 ? 1 : maxLines);
|
|
return lines;
|
|
}
|
|
return [this.tickTrim(label)];
|
|
}
|
|
}
|
|
XAxisTicksComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: XAxisTicksComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
XAxisTicksComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: XAxisTicksComponent, selector: "g[ngx-charts-x-axis-ticks]", inputs: { scale: "scale", orient: "orient", tickArguments: "tickArguments", tickValues: "tickValues", tickStroke: "tickStroke", trimTicks: "trimTicks", maxTickLength: "maxTickLength", tickFormatting: "tickFormatting", showGridLines: "showGridLines", gridLineHeight: "gridLineHeight", width: "width", rotateTicks: "rotateTicks", wrapTicks: "wrapTicks" }, outputs: { dimensionsChanged: "dimensionsChanged" }, viewQueries: [{ propertyName: "ticksElement", first: true, predicate: ["ticksel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g #ticksel>
|
|
<svg:g *ngFor="let tick of ticks" class="tick" [attr.transform]="tickTransform(tick)">
|
|
<ng-container *ngIf="tickFormat(tick) as tickFormatted">
|
|
<title>{{ tickFormatted }}</title>
|
|
<svg:text
|
|
stroke-width="0.01"
|
|
font-size="12px"
|
|
[attr.text-anchor]="textAnchor"
|
|
[attr.transform]="textTransform"
|
|
>
|
|
<ng-container *ngIf="isWrapTicksSupported; then tmplMultilineTick; else tmplSinglelineTick"></ng-container>
|
|
</svg:text>
|
|
|
|
<ng-template #tmplMultilineTick>
|
|
<ng-container *ngIf="tickChunks(tick) as tickLines">
|
|
<svg:tspan *ngFor="let tickLine of tickLines; let i = index" x="0" [attr.y]="i * 12">
|
|
{{ tickLine }}
|
|
</svg:tspan>
|
|
</ng-container>
|
|
</ng-template>
|
|
|
|
<ng-template #tmplSinglelineTick>
|
|
{{ tickTrim(tickFormatted) }}
|
|
</ng-template>
|
|
</ng-container>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let tick of ticks" [attr.transform]="tickTransform(tick)">
|
|
<svg:g *ngIf="showGridLines" [attr.transform]="gridLineTransform()">
|
|
<svg:line class="gridline-path gridline-path-vertical" [attr.y1]="-gridLineHeight" y2="0" />
|
|
</svg:g>
|
|
</svg:g>
|
|
`, isInline: true, directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: XAxisTicksComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-x-axis-ticks]',
|
|
template: `
|
|
<svg:g #ticksel>
|
|
<svg:g *ngFor="let tick of ticks" class="tick" [attr.transform]="tickTransform(tick)">
|
|
<ng-container *ngIf="tickFormat(tick) as tickFormatted">
|
|
<title>{{ tickFormatted }}</title>
|
|
<svg:text
|
|
stroke-width="0.01"
|
|
font-size="12px"
|
|
[attr.text-anchor]="textAnchor"
|
|
[attr.transform]="textTransform"
|
|
>
|
|
<ng-container *ngIf="isWrapTicksSupported; then tmplMultilineTick; else tmplSinglelineTick"></ng-container>
|
|
</svg:text>
|
|
|
|
<ng-template #tmplMultilineTick>
|
|
<ng-container *ngIf="tickChunks(tick) as tickLines">
|
|
<svg:tspan *ngFor="let tickLine of tickLines; let i = index" x="0" [attr.y]="i * 12">
|
|
{{ tickLine }}
|
|
</svg:tspan>
|
|
</ng-container>
|
|
</ng-template>
|
|
|
|
<ng-template #tmplSinglelineTick>
|
|
{{ tickTrim(tickFormatted) }}
|
|
</ng-template>
|
|
</ng-container>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let tick of ticks" [attr.transform]="tickTransform(tick)">
|
|
<svg:g *ngIf="showGridLines" [attr.transform]="gridLineTransform()">
|
|
<svg:line class="gridline-path gridline-path-vertical" [attr.y1]="-gridLineHeight" y2="0" />
|
|
</svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { scale: [{
|
|
type: Input
|
|
}], orient: [{
|
|
type: Input
|
|
}], tickArguments: [{
|
|
type: Input
|
|
}], tickValues: [{
|
|
type: Input
|
|
}], tickStroke: [{
|
|
type: Input
|
|
}], trimTicks: [{
|
|
type: Input
|
|
}], maxTickLength: [{
|
|
type: Input
|
|
}], tickFormatting: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], gridLineHeight: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], rotateTicks: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], dimensionsChanged: [{
|
|
type: Output
|
|
}], ticksElement: [{
|
|
type: ViewChild,
|
|
args: ['ticksel']
|
|
}] } });
|
|
|
|
class XAxisComponent {
|
|
constructor() {
|
|
this.rotateTicks = true;
|
|
this.showGridLines = false;
|
|
this.xOrient = Orientation.Bottom;
|
|
this.xAxisOffset = 0;
|
|
this.wrapTicks = false;
|
|
this.dimensionsChanged = new EventEmitter();
|
|
this.xAxisClassName = 'x axis';
|
|
this.labelOffset = 0;
|
|
this.fill = 'none';
|
|
this.stroke = 'stroke';
|
|
this.tickStroke = '#ccc';
|
|
this.strokeWidth = 'none';
|
|
this.padding = 5;
|
|
this.orientation = Orientation;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.transform = `translate(0,${this.xAxisOffset + this.padding + this.dims.height})`;
|
|
if (typeof this.xAxisTickCount !== 'undefined') {
|
|
this.tickArguments = [this.xAxisTickCount];
|
|
}
|
|
}
|
|
emitTicksHeight({ height }) {
|
|
const newLabelOffset = height + 25 + 5;
|
|
if (newLabelOffset !== this.labelOffset) {
|
|
this.labelOffset = newLabelOffset;
|
|
setTimeout(() => {
|
|
this.dimensionsChanged.emit({ height });
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
XAxisComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: XAxisComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
XAxisComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: { xScale: "xScale", dims: "dims", trimTicks: "trimTicks", rotateTicks: "rotateTicks", maxTickLength: "maxTickLength", tickFormatting: "tickFormatting", showGridLines: "showGridLines", showLabel: "showLabel", labelText: "labelText", ticks: "ticks", xAxisTickCount: "xAxisTickCount", xOrient: "xOrient", xAxisOffset: "xAxisOffset", wrapTicks: "wrapTicks" }, outputs: { dimensionsChanged: "dimensionsChanged" }, viewQueries: [{ propertyName: "ticksComponent", first: true, predicate: XAxisTicksComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g [attr.class]="xAxisClassName" [attr.transform]="transform">
|
|
<svg:g
|
|
ngx-charts-x-axis-ticks
|
|
*ngIf="xScale"
|
|
[trimTicks]="trimTicks"
|
|
[rotateTicks]="rotateTicks"
|
|
[maxTickLength]="maxTickLength"
|
|
[tickFormatting]="tickFormatting"
|
|
[tickArguments]="tickArguments"
|
|
[tickStroke]="tickStroke"
|
|
[scale]="xScale"
|
|
[orient]="xOrient"
|
|
[showGridLines]="showGridLines"
|
|
[gridLineHeight]="dims.height"
|
|
[width]="dims.width"
|
|
[tickValues]="ticks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="emitTicksHeight($event)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-axis-label
|
|
*ngIf="showLabel"
|
|
[label]="labelText"
|
|
[offset]="labelOffset"
|
|
[orient]="orientation.Bottom"
|
|
[height]="dims.height"
|
|
[width]="dims.width"
|
|
></svg:g>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: XAxisTicksComponent, selector: "g[ngx-charts-x-axis-ticks]", inputs: ["scale", "orient", "tickArguments", "tickValues", "tickStroke", "trimTicks", "maxTickLength", "tickFormatting", "showGridLines", "gridLineHeight", "width", "rotateTicks", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: AxisLabelComponent, selector: "g[ngx-charts-axis-label]", inputs: ["orient", "label", "offset", "width", "height"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: XAxisComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-x-axis]',
|
|
template: `
|
|
<svg:g [attr.class]="xAxisClassName" [attr.transform]="transform">
|
|
<svg:g
|
|
ngx-charts-x-axis-ticks
|
|
*ngIf="xScale"
|
|
[trimTicks]="trimTicks"
|
|
[rotateTicks]="rotateTicks"
|
|
[maxTickLength]="maxTickLength"
|
|
[tickFormatting]="tickFormatting"
|
|
[tickArguments]="tickArguments"
|
|
[tickStroke]="tickStroke"
|
|
[scale]="xScale"
|
|
[orient]="xOrient"
|
|
[showGridLines]="showGridLines"
|
|
[gridLineHeight]="dims.height"
|
|
[width]="dims.width"
|
|
[tickValues]="ticks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="emitTicksHeight($event)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-axis-label
|
|
*ngIf="showLabel"
|
|
[label]="labelText"
|
|
[offset]="labelOffset"
|
|
[orient]="orientation.Bottom"
|
|
[height]="dims.height"
|
|
[width]="dims.width"
|
|
></svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { xScale: [{
|
|
type: Input
|
|
}], dims: [{
|
|
type: Input
|
|
}], trimTicks: [{
|
|
type: Input
|
|
}], rotateTicks: [{
|
|
type: Input
|
|
}], maxTickLength: [{
|
|
type: Input
|
|
}], tickFormatting: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], showLabel: [{
|
|
type: Input
|
|
}], labelText: [{
|
|
type: Input
|
|
}], ticks: [{
|
|
type: Input
|
|
}], xAxisTickCount: [{
|
|
type: Input
|
|
}], xOrient: [{
|
|
type: Input
|
|
}], xAxisOffset: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], dimensionsChanged: [{
|
|
type: Output
|
|
}], ticksComponent: [{
|
|
type: ViewChild,
|
|
args: [XAxisTicksComponent]
|
|
}] } });
|
|
|
|
/**
|
|
* Generates a rounded rectanglar path
|
|
*
|
|
* @export
|
|
* @param x, y, w, h, r, tl, tr, bl, br
|
|
*/
|
|
function roundedRect(x, y, w, h, r, [tl, tr, bl, br]) {
|
|
let retval = '';
|
|
w = Math.floor(w);
|
|
h = Math.floor(h);
|
|
w = w === 0 ? 1 : w;
|
|
h = h === 0 ? 1 : h;
|
|
retval = `M${[x + r, y]}`;
|
|
retval += `h${w - 2 * r}`;
|
|
if (tr) {
|
|
retval += `a${[r, r]} 0 0 1 ${[r, r]}`;
|
|
}
|
|
else {
|
|
retval += `h${r}v${r}`;
|
|
}
|
|
retval += `v${h - 2 * r}`;
|
|
if (br) {
|
|
retval += `a${[r, r]} 0 0 1 ${[-r, r]}`;
|
|
}
|
|
else {
|
|
retval += `v${r}h${-r}`;
|
|
}
|
|
retval += `h${2 * r - w}`;
|
|
if (bl) {
|
|
retval += `a${[r, r]} 0 0 1 ${[-r, -r]}`;
|
|
}
|
|
else {
|
|
retval += `h${-r}v${-r}`;
|
|
}
|
|
retval += `v${2 * r - h}`;
|
|
if (tl) {
|
|
retval += `a${[r, r]} 0 0 1 ${[r, -r]}`;
|
|
}
|
|
else {
|
|
retval += `v${-r}h${r}`;
|
|
}
|
|
retval += `z`;
|
|
return retval;
|
|
}
|
|
|
|
class YAxisTicksComponent {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.tickArguments = [5];
|
|
this.tickStroke = '#ccc';
|
|
this.trimTicks = true;
|
|
this.maxTickLength = 16;
|
|
this.showGridLines = false;
|
|
this.showRefLabels = false;
|
|
this.showRefLines = false;
|
|
this.wrapTicks = false;
|
|
this.dimensionsChanged = new EventEmitter();
|
|
this.innerTickSize = 6;
|
|
this.tickPadding = 3;
|
|
this.verticalSpacing = 20;
|
|
this.textAnchor = TextAnchor.Middle;
|
|
this.width = 0;
|
|
this.outerTickSize = 6;
|
|
this.rotateLabels = false;
|
|
this.referenceLineLength = 0;
|
|
this.Orientation = Orientation;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
ngAfterViewInit() {
|
|
setTimeout(() => this.updateDims());
|
|
}
|
|
updateDims() {
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
// for SSR, use approximate value instead of measured
|
|
this.width = this.getApproximateAxisWidth();
|
|
this.dimensionsChanged.emit({ width: this.width });
|
|
return;
|
|
}
|
|
const width = parseInt(this.ticksElement.nativeElement.getBoundingClientRect().width, 10);
|
|
if (width !== this.width) {
|
|
this.width = width;
|
|
this.dimensionsChanged.emit({ width });
|
|
setTimeout(() => this.updateDims());
|
|
}
|
|
}
|
|
update() {
|
|
const scale = this.scale;
|
|
const sign = this.orient === Orientation.Top || this.orient === Orientation.Right ? -1 : 1;
|
|
this.tickSpacing = Math.max(this.innerTickSize, 0) + this.tickPadding;
|
|
this.ticks = this.getTicks();
|
|
if (this.tickFormatting) {
|
|
this.tickFormat = this.tickFormatting;
|
|
}
|
|
else if (scale.tickFormat) {
|
|
// eslint-disable-next-line prefer-spread
|
|
this.tickFormat = scale.tickFormat.apply(scale, this.tickArguments);
|
|
}
|
|
else {
|
|
this.tickFormat = function (d) {
|
|
if (d.constructor.name === 'Date') {
|
|
return d.toLocaleDateString();
|
|
}
|
|
return d.toLocaleString();
|
|
};
|
|
}
|
|
this.adjustedScale = scale.bandwidth
|
|
? d => {
|
|
// position the tick to middle considering number of lines of the tick
|
|
const positionMiddle = scale(d) + scale.bandwidth() * 0.5;
|
|
if (this.wrapTicks && d.toString().length > this.maxTickLength) {
|
|
const chunksLength = this.tickChunks(d).length;
|
|
if (chunksLength === 1) {
|
|
return positionMiddle;
|
|
}
|
|
const bandWidth = scale.bandwidth();
|
|
const heightOfLines = chunksLength * 8;
|
|
const availableFreeSpace = bandWidth * 0.5 - heightOfLines * 0.5;
|
|
return scale(d) + availableFreeSpace;
|
|
}
|
|
return positionMiddle;
|
|
}
|
|
: scale;
|
|
if (this.showRefLines && this.referenceLines) {
|
|
this.setReferencelines();
|
|
}
|
|
switch (this.orient) {
|
|
case Orientation.Top:
|
|
this.transform = function (tick) {
|
|
return 'translate(' + this.adjustedScale(tick) + ',0)';
|
|
};
|
|
this.textAnchor = TextAnchor.Middle;
|
|
this.y2 = this.innerTickSize * sign;
|
|
this.y1 = this.tickSpacing * sign;
|
|
this.dy = sign < 0 ? '0em' : '.71em';
|
|
break;
|
|
case Orientation.Bottom:
|
|
this.transform = function (tick) {
|
|
return 'translate(' + this.adjustedScale(tick) + ',0)';
|
|
};
|
|
this.textAnchor = TextAnchor.Middle;
|
|
this.y2 = this.innerTickSize * sign;
|
|
this.y1 = this.tickSpacing * sign;
|
|
this.dy = sign < 0 ? '0em' : '.71em';
|
|
break;
|
|
case Orientation.Left:
|
|
this.transform = function (tick) {
|
|
return 'translate(0,' + this.adjustedScale(tick) + ')';
|
|
};
|
|
this.textAnchor = TextAnchor.End;
|
|
this.x2 = this.innerTickSize * -sign;
|
|
this.x1 = this.tickSpacing * -sign;
|
|
this.dy = '.32em';
|
|
break;
|
|
case Orientation.Right:
|
|
this.transform = function (tick) {
|
|
return 'translate(0,' + this.adjustedScale(tick) + ')';
|
|
};
|
|
this.textAnchor = TextAnchor.Start;
|
|
this.x2 = this.innerTickSize * -sign;
|
|
this.x1 = this.tickSpacing * -sign;
|
|
this.dy = '.32em';
|
|
break;
|
|
default:
|
|
}
|
|
setTimeout(() => this.updateDims());
|
|
}
|
|
setReferencelines() {
|
|
this.refMin = this.adjustedScale(Math.min.apply(null, this.referenceLines.map(item => item.value)));
|
|
this.refMax = this.adjustedScale(Math.max.apply(null, this.referenceLines.map(item => item.value)));
|
|
this.referenceLineLength = this.referenceLines.length;
|
|
this.referenceAreaPath = roundedRect(0, this.refMax, this.gridLineWidth, this.refMin - this.refMax, 0, [
|
|
false,
|
|
false,
|
|
false,
|
|
false
|
|
]);
|
|
}
|
|
getTicks() {
|
|
let ticks;
|
|
const maxTicks = this.getMaxTicks(20);
|
|
const maxScaleTicks = this.getMaxTicks(50);
|
|
if (this.tickValues) {
|
|
ticks = this.tickValues;
|
|
}
|
|
else if (this.scale.ticks) {
|
|
ticks = this.scale.ticks.apply(this.scale, [maxScaleTicks]);
|
|
}
|
|
else {
|
|
ticks = this.scale.domain();
|
|
ticks = reduceTicks(ticks, maxTicks);
|
|
}
|
|
return ticks;
|
|
}
|
|
getMaxTicks(tickHeight) {
|
|
return Math.floor(this.height / tickHeight);
|
|
}
|
|
tickTransform(tick) {
|
|
return `translate(${this.adjustedScale(tick)},${this.verticalSpacing})`;
|
|
}
|
|
gridLineTransform() {
|
|
return `translate(5,0)`;
|
|
}
|
|
tickTrim(label) {
|
|
return this.trimTicks ? trimLabel(label, this.maxTickLength) : label;
|
|
}
|
|
getApproximateAxisWidth() {
|
|
const maxChars = Math.max(...this.ticks.map(t => this.tickTrim(this.tickFormat(t)).length));
|
|
const charWidth = 7;
|
|
return maxChars * charWidth;
|
|
}
|
|
tickChunks(label) {
|
|
if (label.toString().length > this.maxTickLength && this.scale.bandwidth) {
|
|
// for y-axis the width of the tick is fixed
|
|
const preferredWidth = this.maxTickLength;
|
|
const maxLines = Math.floor(this.scale.bandwidth() / 15);
|
|
if (maxLines <= 1) {
|
|
return [this.tickTrim(label)];
|
|
}
|
|
return getTickLines(label, preferredWidth, Math.min(maxLines, 5));
|
|
}
|
|
return [this.tickFormat(label)];
|
|
}
|
|
}
|
|
YAxisTicksComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: YAxisTicksComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
YAxisTicksComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: YAxisTicksComponent, selector: "g[ngx-charts-y-axis-ticks]", inputs: { scale: "scale", orient: "orient", tickArguments: "tickArguments", tickValues: "tickValues", tickStroke: "tickStroke", trimTicks: "trimTicks", maxTickLength: "maxTickLength", tickFormatting: "tickFormatting", showGridLines: "showGridLines", gridLineWidth: "gridLineWidth", height: "height", referenceLines: "referenceLines", showRefLabels: "showRefLabels", showRefLines: "showRefLines", wrapTicks: "wrapTicks" }, outputs: { dimensionsChanged: "dimensionsChanged" }, viewQueries: [{ propertyName: "ticksElement", first: true, predicate: ["ticksel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g #ticksel>
|
|
<svg:g *ngFor="let tick of ticks" class="tick" [attr.transform]="transform(tick)">
|
|
<ng-container *ngIf="tickFormat(tick) as tickFormatted">
|
|
<title>{{ tickFormatted }}</title>
|
|
<svg:text
|
|
stroke-width="0.01"
|
|
[attr.dy]="dy"
|
|
[attr.x]="x1"
|
|
[attr.y]="y1"
|
|
[attr.text-anchor]="textAnchor"
|
|
[style.font-size]="'12px'"
|
|
>
|
|
<ng-container *ngIf="wrapTicks; then tmplMultilineTick; else tmplSinglelineTick"></ng-container>
|
|
</svg:text>
|
|
|
|
<ng-template #tmplMultilineTick>
|
|
<ng-container *ngIf="tickChunks(tick) as tickLines">
|
|
<ng-container *ngIf="tickLines.length > 1; else tmplSinglelineTick">
|
|
<svg:tspan *ngFor="let tickLine of tickLines; let i = index" x="0" [attr.y]="i * (8 + tickSpacing)">
|
|
{{ tickLine }}
|
|
</svg:tspan>
|
|
</ng-container>
|
|
</ng-container>
|
|
</ng-template>
|
|
|
|
<ng-template #tmplSinglelineTick>
|
|
{{ tickTrim(tickFormatted) }}
|
|
</ng-template>
|
|
</ng-container>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:path
|
|
*ngIf="referenceLineLength > 1 && refMax && refMin && showRefLines"
|
|
class="reference-area"
|
|
[attr.d]="referenceAreaPath"
|
|
[attr.transform]="gridLineTransform()"
|
|
/>
|
|
<svg:g *ngFor="let tick of ticks" [attr.transform]="transform(tick)">
|
|
<svg:g *ngIf="showGridLines" [attr.transform]="gridLineTransform()">
|
|
<svg:line
|
|
*ngIf="orient === Orientation.Left"
|
|
class="gridline-path gridline-path-horizontal"
|
|
x1="0"
|
|
[attr.x2]="gridLineWidth"
|
|
/>
|
|
<svg:line
|
|
*ngIf="orient === Orientation.Right"
|
|
class="gridline-path gridline-path-horizontal"
|
|
x1="0"
|
|
[attr.x2]="-gridLineWidth"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let refLine of referenceLines">
|
|
<svg:g *ngIf="showRefLines" [attr.transform]="transform(refLine.value)">
|
|
<svg:line
|
|
class="refline-path gridline-path-horizontal"
|
|
x1="0"
|
|
[attr.x2]="gridLineWidth"
|
|
[attr.transform]="gridLineTransform()"
|
|
/>
|
|
<svg:g *ngIf="showRefLabels">
|
|
<title>{{ tickTrim(tickFormat(refLine.value)) }}</title>
|
|
<svg:text
|
|
class="refline-label"
|
|
[attr.dy]="dy"
|
|
[attr.y]="-6"
|
|
[attr.x]="gridLineWidth"
|
|
[attr.text-anchor]="textAnchor"
|
|
>
|
|
{{ refLine.name }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
`, isInline: true, directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: YAxisTicksComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-y-axis-ticks]',
|
|
template: `
|
|
<svg:g #ticksel>
|
|
<svg:g *ngFor="let tick of ticks" class="tick" [attr.transform]="transform(tick)">
|
|
<ng-container *ngIf="tickFormat(tick) as tickFormatted">
|
|
<title>{{ tickFormatted }}</title>
|
|
<svg:text
|
|
stroke-width="0.01"
|
|
[attr.dy]="dy"
|
|
[attr.x]="x1"
|
|
[attr.y]="y1"
|
|
[attr.text-anchor]="textAnchor"
|
|
[style.font-size]="'12px'"
|
|
>
|
|
<ng-container *ngIf="wrapTicks; then tmplMultilineTick; else tmplSinglelineTick"></ng-container>
|
|
</svg:text>
|
|
|
|
<ng-template #tmplMultilineTick>
|
|
<ng-container *ngIf="tickChunks(tick) as tickLines">
|
|
<ng-container *ngIf="tickLines.length > 1; else tmplSinglelineTick">
|
|
<svg:tspan *ngFor="let tickLine of tickLines; let i = index" x="0" [attr.y]="i * (8 + tickSpacing)">
|
|
{{ tickLine }}
|
|
</svg:tspan>
|
|
</ng-container>
|
|
</ng-container>
|
|
</ng-template>
|
|
|
|
<ng-template #tmplSinglelineTick>
|
|
{{ tickTrim(tickFormatted) }}
|
|
</ng-template>
|
|
</ng-container>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:path
|
|
*ngIf="referenceLineLength > 1 && refMax && refMin && showRefLines"
|
|
class="reference-area"
|
|
[attr.d]="referenceAreaPath"
|
|
[attr.transform]="gridLineTransform()"
|
|
/>
|
|
<svg:g *ngFor="let tick of ticks" [attr.transform]="transform(tick)">
|
|
<svg:g *ngIf="showGridLines" [attr.transform]="gridLineTransform()">
|
|
<svg:line
|
|
*ngIf="orient === Orientation.Left"
|
|
class="gridline-path gridline-path-horizontal"
|
|
x1="0"
|
|
[attr.x2]="gridLineWidth"
|
|
/>
|
|
<svg:line
|
|
*ngIf="orient === Orientation.Right"
|
|
class="gridline-path gridline-path-horizontal"
|
|
x1="0"
|
|
[attr.x2]="-gridLineWidth"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let refLine of referenceLines">
|
|
<svg:g *ngIf="showRefLines" [attr.transform]="transform(refLine.value)">
|
|
<svg:line
|
|
class="refline-path gridline-path-horizontal"
|
|
x1="0"
|
|
[attr.x2]="gridLineWidth"
|
|
[attr.transform]="gridLineTransform()"
|
|
/>
|
|
<svg:g *ngIf="showRefLabels">
|
|
<title>{{ tickTrim(tickFormat(refLine.value)) }}</title>
|
|
<svg:text
|
|
class="refline-label"
|
|
[attr.dy]="dy"
|
|
[attr.y]="-6"
|
|
[attr.x]="gridLineWidth"
|
|
[attr.text-anchor]="textAnchor"
|
|
>
|
|
{{ refLine.name }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { scale: [{
|
|
type: Input
|
|
}], orient: [{
|
|
type: Input
|
|
}], tickArguments: [{
|
|
type: Input
|
|
}], tickValues: [{
|
|
type: Input
|
|
}], tickStroke: [{
|
|
type: Input
|
|
}], trimTicks: [{
|
|
type: Input
|
|
}], maxTickLength: [{
|
|
type: Input
|
|
}], tickFormatting: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], gridLineWidth: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], referenceLines: [{
|
|
type: Input
|
|
}], showRefLabels: [{
|
|
type: Input
|
|
}], showRefLines: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], dimensionsChanged: [{
|
|
type: Output
|
|
}], ticksElement: [{
|
|
type: ViewChild,
|
|
args: ['ticksel']
|
|
}] } });
|
|
|
|
class YAxisComponent {
|
|
constructor() {
|
|
this.showGridLines = false;
|
|
this.yOrient = Orientation.Left;
|
|
this.yAxisOffset = 0;
|
|
this.wrapTicks = false;
|
|
this.dimensionsChanged = new EventEmitter();
|
|
this.yAxisClassName = 'y axis';
|
|
this.labelOffset = 15;
|
|
this.fill = 'none';
|
|
this.stroke = '#CCC';
|
|
this.tickStroke = '#CCC';
|
|
this.strokeWidth = 1;
|
|
this.padding = 5;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.offset = -(this.yAxisOffset + this.padding);
|
|
if (this.yOrient === Orientation.Right) {
|
|
this.labelOffset = 65;
|
|
this.transform = `translate(${this.offset + this.dims.width} , 0)`;
|
|
}
|
|
else {
|
|
this.transform = `translate(${this.offset} , 0)`;
|
|
}
|
|
if (this.yAxisTickCount !== undefined) {
|
|
this.tickArguments = [this.yAxisTickCount];
|
|
}
|
|
}
|
|
emitTicksWidth({ width }) {
|
|
if (width !== this.labelOffset && this.yOrient === Orientation.Right) {
|
|
this.labelOffset = width + this.labelOffset;
|
|
setTimeout(() => {
|
|
this.dimensionsChanged.emit({ width });
|
|
}, 0);
|
|
}
|
|
else if (width !== this.labelOffset) {
|
|
this.labelOffset = width;
|
|
setTimeout(() => {
|
|
this.dimensionsChanged.emit({ width });
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
YAxisComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: YAxisComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
YAxisComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: { yScale: "yScale", dims: "dims", trimTicks: "trimTicks", maxTickLength: "maxTickLength", tickFormatting: "tickFormatting", ticks: "ticks", showGridLines: "showGridLines", showLabel: "showLabel", labelText: "labelText", yAxisTickCount: "yAxisTickCount", yOrient: "yOrient", referenceLines: "referenceLines", showRefLines: "showRefLines", showRefLabels: "showRefLabels", yAxisOffset: "yAxisOffset", wrapTicks: "wrapTicks" }, outputs: { dimensionsChanged: "dimensionsChanged" }, viewQueries: [{ propertyName: "ticksComponent", first: true, predicate: YAxisTicksComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g [attr.class]="yAxisClassName" [attr.transform]="transform">
|
|
<svg:g
|
|
ngx-charts-y-axis-ticks
|
|
*ngIf="yScale"
|
|
[trimTicks]="trimTicks"
|
|
[maxTickLength]="maxTickLength"
|
|
[tickFormatting]="tickFormatting"
|
|
[tickArguments]="tickArguments"
|
|
[tickValues]="ticks"
|
|
[tickStroke]="tickStroke"
|
|
[scale]="yScale"
|
|
[orient]="yOrient"
|
|
[showGridLines]="showGridLines"
|
|
[gridLineWidth]="dims.width"
|
|
[referenceLines]="referenceLines"
|
|
[showRefLines]="showRefLines"
|
|
[showRefLabels]="showRefLabels"
|
|
[height]="dims.height"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="emitTicksWidth($event)"
|
|
/>
|
|
|
|
<svg:g
|
|
ngx-charts-axis-label
|
|
*ngIf="showLabel"
|
|
[label]="labelText"
|
|
[offset]="labelOffset"
|
|
[orient]="yOrient"
|
|
[height]="dims.height"
|
|
[width]="dims.width"
|
|
></svg:g>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: YAxisTicksComponent, selector: "g[ngx-charts-y-axis-ticks]", inputs: ["scale", "orient", "tickArguments", "tickValues", "tickStroke", "trimTicks", "maxTickLength", "tickFormatting", "showGridLines", "gridLineWidth", "height", "referenceLines", "showRefLabels", "showRefLines", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: AxisLabelComponent, selector: "g[ngx-charts-axis-label]", inputs: ["orient", "label", "offset", "width", "height"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: YAxisComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-y-axis]',
|
|
template: `
|
|
<svg:g [attr.class]="yAxisClassName" [attr.transform]="transform">
|
|
<svg:g
|
|
ngx-charts-y-axis-ticks
|
|
*ngIf="yScale"
|
|
[trimTicks]="trimTicks"
|
|
[maxTickLength]="maxTickLength"
|
|
[tickFormatting]="tickFormatting"
|
|
[tickArguments]="tickArguments"
|
|
[tickValues]="ticks"
|
|
[tickStroke]="tickStroke"
|
|
[scale]="yScale"
|
|
[orient]="yOrient"
|
|
[showGridLines]="showGridLines"
|
|
[gridLineWidth]="dims.width"
|
|
[referenceLines]="referenceLines"
|
|
[showRefLines]="showRefLines"
|
|
[showRefLabels]="showRefLabels"
|
|
[height]="dims.height"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="emitTicksWidth($event)"
|
|
/>
|
|
|
|
<svg:g
|
|
ngx-charts-axis-label
|
|
*ngIf="showLabel"
|
|
[label]="labelText"
|
|
[offset]="labelOffset"
|
|
[orient]="yOrient"
|
|
[height]="dims.height"
|
|
[width]="dims.width"
|
|
></svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { yScale: [{
|
|
type: Input
|
|
}], dims: [{
|
|
type: Input
|
|
}], trimTicks: [{
|
|
type: Input
|
|
}], maxTickLength: [{
|
|
type: Input
|
|
}], tickFormatting: [{
|
|
type: Input
|
|
}], ticks: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], showLabel: [{
|
|
type: Input
|
|
}], labelText: [{
|
|
type: Input
|
|
}], yAxisTickCount: [{
|
|
type: Input
|
|
}], yOrient: [{
|
|
type: Input
|
|
}], referenceLines: [{
|
|
type: Input
|
|
}], showRefLines: [{
|
|
type: Input
|
|
}], showRefLabels: [{
|
|
type: Input
|
|
}], yAxisOffset: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], dimensionsChanged: [{
|
|
type: Output
|
|
}], ticksComponent: [{
|
|
type: ViewChild,
|
|
args: [YAxisTicksComponent]
|
|
}] } });
|
|
|
|
class AxesModule {
|
|
}
|
|
AxesModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AxesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
AxesModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AxesModule, declarations: [AxisLabelComponent, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent], imports: [CommonModule], exports: [AxisLabelComponent, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent] });
|
|
AxesModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AxesModule, imports: [[CommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AxesModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [CommonModule],
|
|
declarations: [AxisLabelComponent, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent],
|
|
exports: [AxisLabelComponent, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent]
|
|
}]
|
|
}] });
|
|
|
|
var StyleTypes;
|
|
(function (StyleTypes) {
|
|
StyleTypes["popover"] = "popover";
|
|
StyleTypes["tooltip"] = "tooltip";
|
|
})(StyleTypes || (StyleTypes = {}));
|
|
|
|
var ShowTypes;
|
|
(function (ShowTypes) {
|
|
ShowTypes[ShowTypes["all"] = 'all'] = "all";
|
|
ShowTypes[ShowTypes["focus"] = 'focus'] = "focus";
|
|
ShowTypes[ShowTypes["mouseover"] = 'mouseover'] = "mouseover";
|
|
})(ShowTypes || (ShowTypes = {}));
|
|
|
|
class TooltipDirective {
|
|
constructor(tooltipService, viewContainerRef, renderer) {
|
|
this.tooltipService = tooltipService;
|
|
this.viewContainerRef = viewContainerRef;
|
|
this.renderer = renderer;
|
|
this.tooltipCssClass = '';
|
|
this.tooltipAppendToBody = true;
|
|
this.tooltipSpacing = 10;
|
|
this.tooltipDisabled = false;
|
|
this.tooltipShowCaret = true;
|
|
this.tooltipPlacement = PlacementTypes.Top;
|
|
this.tooltipAlignment = PlacementTypes.Center;
|
|
this.tooltipType = StyleTypes.popover;
|
|
this.tooltipCloseOnClickOutside = true;
|
|
this.tooltipCloseOnMouseLeave = true;
|
|
this.tooltipHideTimeout = 300;
|
|
this.tooltipShowTimeout = 100;
|
|
this.tooltipShowEvent = ShowTypes.all;
|
|
this.tooltipImmediateExit = false;
|
|
this.show = new EventEmitter();
|
|
this.hide = new EventEmitter();
|
|
}
|
|
get listensForFocus() {
|
|
return this.tooltipShowEvent === ShowTypes.all || this.tooltipShowEvent === ShowTypes.focus;
|
|
}
|
|
get listensForHover() {
|
|
return this.tooltipShowEvent === ShowTypes.all || this.tooltipShowEvent === ShowTypes.mouseover;
|
|
}
|
|
ngOnDestroy() {
|
|
this.hideTooltip(true);
|
|
}
|
|
onFocus() {
|
|
if (this.listensForFocus) {
|
|
this.showTooltip();
|
|
}
|
|
}
|
|
onBlur() {
|
|
if (this.listensForFocus) {
|
|
this.hideTooltip(true);
|
|
}
|
|
}
|
|
onMouseEnter() {
|
|
if (this.listensForHover) {
|
|
this.showTooltip();
|
|
}
|
|
}
|
|
onMouseLeave(target) {
|
|
if (this.listensForHover && this.tooltipCloseOnMouseLeave) {
|
|
clearTimeout(this.timeout);
|
|
if (this.component) {
|
|
const contentDom = this.component.instance.element.nativeElement;
|
|
const contains = contentDom.contains(target);
|
|
if (contains)
|
|
return;
|
|
}
|
|
this.hideTooltip(this.tooltipImmediateExit);
|
|
}
|
|
}
|
|
onMouseClick() {
|
|
if (this.listensForHover) {
|
|
this.hideTooltip(true);
|
|
}
|
|
}
|
|
showTooltip(immediate) {
|
|
if (this.component || this.tooltipDisabled)
|
|
return;
|
|
const time = immediate
|
|
? 0
|
|
: this.tooltipShowTimeout + (navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) ? 400 : 0);
|
|
clearTimeout(this.timeout);
|
|
this.timeout = setTimeout(() => {
|
|
this.tooltipService.destroyAll();
|
|
const options = this.createBoundOptions();
|
|
this.component = this.tooltipService.create(options);
|
|
// add a tiny timeout to avoid event re-triggers
|
|
setTimeout(() => {
|
|
if (this.component) {
|
|
this.addHideListeners(this.component.instance.element.nativeElement);
|
|
}
|
|
}, 10);
|
|
this.show.emit(true);
|
|
}, time);
|
|
}
|
|
addHideListeners(tooltip) {
|
|
// on mouse enter, cancel the hide triggered by the leave
|
|
this.mouseEnterContentEvent = this.renderer.listen(tooltip, 'mouseenter', () => {
|
|
clearTimeout(this.timeout);
|
|
});
|
|
// content mouse leave listener
|
|
if (this.tooltipCloseOnMouseLeave) {
|
|
this.mouseLeaveContentEvent = this.renderer.listen(tooltip, 'mouseleave', () => {
|
|
this.hideTooltip(this.tooltipImmediateExit);
|
|
});
|
|
}
|
|
// content close on click outside
|
|
if (this.tooltipCloseOnClickOutside) {
|
|
this.documentClickEvent = this.renderer.listen('window', 'click', event => {
|
|
const contains = tooltip.contains(event.target);
|
|
if (!contains)
|
|
this.hideTooltip();
|
|
});
|
|
}
|
|
}
|
|
hideTooltip(immediate = false) {
|
|
if (!this.component)
|
|
return;
|
|
const destroyFn = () => {
|
|
// remove events
|
|
if (this.mouseLeaveContentEvent)
|
|
this.mouseLeaveContentEvent();
|
|
if (this.mouseEnterContentEvent)
|
|
this.mouseEnterContentEvent();
|
|
if (this.documentClickEvent)
|
|
this.documentClickEvent();
|
|
// emit events
|
|
this.hide.emit(true);
|
|
// destroy component
|
|
this.tooltipService.destroy(this.component);
|
|
this.component = undefined;
|
|
};
|
|
clearTimeout(this.timeout);
|
|
if (!immediate) {
|
|
this.timeout = setTimeout(destroyFn, this.tooltipHideTimeout);
|
|
}
|
|
else {
|
|
destroyFn();
|
|
}
|
|
}
|
|
createBoundOptions() {
|
|
return {
|
|
title: this.tooltipTitle,
|
|
template: this.tooltipTemplate,
|
|
host: this.viewContainerRef.element,
|
|
placement: this.tooltipPlacement,
|
|
alignment: this.tooltipAlignment,
|
|
type: this.tooltipType,
|
|
showCaret: this.tooltipShowCaret,
|
|
cssClass: this.tooltipCssClass,
|
|
spacing: this.tooltipSpacing,
|
|
context: this.tooltipContext
|
|
};
|
|
}
|
|
}
|
|
TooltipDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipDirective, deps: [{ token: TooltipService }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
|
|
TooltipDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.1.0", type: TooltipDirective, selector: "[ngx-tooltip]", inputs: { tooltipCssClass: "tooltipCssClass", tooltipTitle: "tooltipTitle", tooltipAppendToBody: "tooltipAppendToBody", tooltipSpacing: "tooltipSpacing", tooltipDisabled: "tooltipDisabled", tooltipShowCaret: "tooltipShowCaret", tooltipPlacement: "tooltipPlacement", tooltipAlignment: "tooltipAlignment", tooltipType: "tooltipType", tooltipCloseOnClickOutside: "tooltipCloseOnClickOutside", tooltipCloseOnMouseLeave: "tooltipCloseOnMouseLeave", tooltipHideTimeout: "tooltipHideTimeout", tooltipShowTimeout: "tooltipShowTimeout", tooltipTemplate: "tooltipTemplate", tooltipShowEvent: "tooltipShowEvent", tooltipContext: "tooltipContext", tooltipImmediateExit: "tooltipImmediateExit" }, outputs: { show: "show", hide: "hide" }, host: { listeners: { "focusin": "onFocus()", "blur": "onBlur()", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave($event.target)", "click": "onMouseClick()" } }, ngImport: i0 });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipDirective, decorators: [{
|
|
type: Directive,
|
|
args: [{ selector: '[ngx-tooltip]' }]
|
|
}], ctorParameters: function () { return [{ type: TooltipService }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }]; }, propDecorators: { tooltipCssClass: [{
|
|
type: Input
|
|
}], tooltipTitle: [{
|
|
type: Input
|
|
}], tooltipAppendToBody: [{
|
|
type: Input
|
|
}], tooltipSpacing: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipShowCaret: [{
|
|
type: Input
|
|
}], tooltipPlacement: [{
|
|
type: Input
|
|
}], tooltipAlignment: [{
|
|
type: Input
|
|
}], tooltipType: [{
|
|
type: Input
|
|
}], tooltipCloseOnClickOutside: [{
|
|
type: Input
|
|
}], tooltipCloseOnMouseLeave: [{
|
|
type: Input
|
|
}], tooltipHideTimeout: [{
|
|
type: Input
|
|
}], tooltipShowTimeout: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], tooltipShowEvent: [{
|
|
type: Input
|
|
}], tooltipContext: [{
|
|
type: Input
|
|
}], tooltipImmediateExit: [{
|
|
type: Input
|
|
}], show: [{
|
|
type: Output
|
|
}], hide: [{
|
|
type: Output
|
|
}], onFocus: [{
|
|
type: HostListener,
|
|
args: ['focusin']
|
|
}], onBlur: [{
|
|
type: HostListener,
|
|
args: ['blur']
|
|
}], onMouseEnter: [{
|
|
type: HostListener,
|
|
args: ['mouseenter']
|
|
}], onMouseLeave: [{
|
|
type: HostListener,
|
|
args: ['mouseleave', ['$event.target']]
|
|
}], onMouseClick: [{
|
|
type: HostListener,
|
|
args: ['click']
|
|
}] } });
|
|
|
|
class TooltipModule {
|
|
}
|
|
TooltipModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
TooltipModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipModule, declarations: [TooltipContentComponent, TooltipDirective], imports: [CommonModule], exports: [TooltipContentComponent, TooltipDirective] });
|
|
TooltipModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipModule, providers: [InjectionService, TooltipService], imports: [[CommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
declarations: [TooltipContentComponent, TooltipDirective],
|
|
providers: [InjectionService, TooltipService],
|
|
exports: [TooltipContentComponent, TooltipDirective],
|
|
imports: [CommonModule],
|
|
entryComponents: [TooltipContentComponent]
|
|
}]
|
|
}] });
|
|
|
|
const cache = {};
|
|
/**
|
|
* Generates a short id.
|
|
*
|
|
* Description:
|
|
* A 4-character alphanumeric sequence (364 = 1.6 million)
|
|
* This should only be used for JavaScript specific models.
|
|
* http://stackoverflow.com/questions/6248666/how-to-generate-short-uid-like-ax4j9z-in-js
|
|
*
|
|
* Example: `ebgf`
|
|
*/
|
|
function id() {
|
|
let newId = ('0000' + ((Math.random() * Math.pow(36, 4)) << 0).toString(36)).slice(-4);
|
|
// append a 'a' because neo gets mad
|
|
newId = `a${newId}`;
|
|
// ensure not already used
|
|
if (!cache[newId]) {
|
|
cache[newId] = true;
|
|
return newId;
|
|
}
|
|
return id();
|
|
}
|
|
|
|
var BarOrientation;
|
|
(function (BarOrientation) {
|
|
BarOrientation["Vertical"] = "vertical";
|
|
BarOrientation["Horizontal"] = "horizontal";
|
|
})(BarOrientation || (BarOrientation = {}));
|
|
|
|
class SvgLinearGradientComponent {
|
|
constructor() {
|
|
this.orientation = BarOrientation.Vertical;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.x1 = '0%';
|
|
this.x2 = '0%';
|
|
this.y1 = '0%';
|
|
this.y2 = '0%';
|
|
if (this.orientation === BarOrientation.Horizontal) {
|
|
this.x2 = '100%';
|
|
}
|
|
else if (this.orientation === BarOrientation.Vertical) {
|
|
this.y1 = '100%';
|
|
}
|
|
}
|
|
}
|
|
SvgLinearGradientComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SvgLinearGradientComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
SvgLinearGradientComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: { orientation: "orientation", name: "name", stops: "stops" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:linearGradient [id]="name" [attr.x1]="x1" [attr.y1]="y1" [attr.x2]="x2" [attr.y2]="y2">
|
|
<svg:stop
|
|
*ngFor="let stop of stops"
|
|
[attr.offset]="stop.offset + '%'"
|
|
[style.stop-color]="stop.color"
|
|
[style.stop-opacity]="stop.opacity"
|
|
/>
|
|
</svg:linearGradient>
|
|
`, isInline: true, directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SvgLinearGradientComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-svg-linear-gradient]',
|
|
template: `
|
|
<svg:linearGradient [id]="name" [attr.x1]="x1" [attr.y1]="y1" [attr.x2]="x2" [attr.y2]="y2">
|
|
<svg:stop
|
|
*ngFor="let stop of stops"
|
|
[attr.offset]="stop.offset + '%'"
|
|
[style.stop-color]="stop.color"
|
|
[style.stop-opacity]="stop.opacity"
|
|
/>
|
|
</svg:linearGradient>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { orientation: [{
|
|
type: Input
|
|
}], name: [{
|
|
type: Input
|
|
}], stops: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class CircleComponent {
|
|
constructor() {
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
}
|
|
onClick() {
|
|
this.select.emit(this.data);
|
|
}
|
|
onMouseEnter() {
|
|
this.activate.emit(this.data);
|
|
}
|
|
onMouseLeave() {
|
|
this.deactivate.emit(this.data);
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.classNames = Array.isArray(this.classNames) ? this.classNames.join(' ') : '';
|
|
this.classNames += 'circle';
|
|
}
|
|
}
|
|
CircleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CircleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
CircleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: CircleComponent, selector: "g[ngx-charts-circle]", inputs: { cx: "cx", cy: "cy", r: "r", fill: "fill", stroke: "stroke", data: "data", classNames: "classNames", circleOpacity: "circleOpacity", pointerEvents: "pointerEvents" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, host: { listeners: { "click": "onClick()", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:circle
|
|
[attr.cx]="cx"
|
|
[attr.cy]="cy"
|
|
[attr.r]="r"
|
|
[attr.fill]="fill"
|
|
[attr.stroke]="stroke"
|
|
[attr.opacity]="circleOpacity"
|
|
[attr.class]="classNames"
|
|
[attr.pointer-events]="pointerEvents"
|
|
/>
|
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CircleComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-circle]',
|
|
template: `
|
|
<svg:circle
|
|
[attr.cx]="cx"
|
|
[attr.cy]="cy"
|
|
[attr.r]="r"
|
|
[attr.fill]="fill"
|
|
[attr.stroke]="stroke"
|
|
[attr.opacity]="circleOpacity"
|
|
[attr.class]="classNames"
|
|
[attr.pointer-events]="pointerEvents"
|
|
/>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { cx: [{
|
|
type: Input
|
|
}], cy: [{
|
|
type: Input
|
|
}], r: [{
|
|
type: Input
|
|
}], fill: [{
|
|
type: Input
|
|
}], stroke: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], classNames: [{
|
|
type: Input
|
|
}], circleOpacity: [{
|
|
type: Input
|
|
}], pointerEvents: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], onClick: [{
|
|
type: HostListener,
|
|
args: ['click']
|
|
}], onMouseEnter: [{
|
|
type: HostListener,
|
|
args: ['mouseenter']
|
|
}], onMouseLeave: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
var SeriesType;
|
|
(function (SeriesType) {
|
|
SeriesType["Standard"] = "standard";
|
|
SeriesType["Stacked"] = "stacked";
|
|
})(SeriesType || (SeriesType = {}));
|
|
class CircleSeriesComponent {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.type = SeriesType.Standard;
|
|
this.tooltipDisabled = false;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.barVisible = false;
|
|
this.barOrientation = BarOrientation;
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientFill = `url(#${this.gradientId})`;
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
ngOnChanges() {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.circle = this.getActiveCircle();
|
|
}
|
|
getActiveCircle() {
|
|
const indexActiveDataPoint = this.data.series.findIndex(d => {
|
|
const label = d.name;
|
|
return label && this.visibleValue && label.toString() === this.visibleValue.toString() && d.value !== undefined;
|
|
});
|
|
if (indexActiveDataPoint === -1) {
|
|
// No valid point is 'active/hovered over' at this moment.
|
|
return undefined;
|
|
}
|
|
return this.mapDataPointToCircle(this.data.series[indexActiveDataPoint], indexActiveDataPoint);
|
|
}
|
|
mapDataPointToCircle(d, i) {
|
|
const seriesName = this.data.name;
|
|
const value = d.value;
|
|
const label = d.name;
|
|
const tooltipLabel = formatLabel(label);
|
|
let cx;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
cx = this.xScale(label);
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
cx = this.xScale(Number(label));
|
|
}
|
|
else {
|
|
cx = this.xScale(label);
|
|
}
|
|
const cy = this.yScale(this.type === SeriesType.Standard ? value : d.d1);
|
|
const radius = 5;
|
|
const height = this.yScale.range()[0] - cy;
|
|
const opacity = 1;
|
|
let color;
|
|
if (this.colors.scaleType === ScaleType.Linear) {
|
|
if (this.type === SeriesType.Standard) {
|
|
color = this.colors.getColor(value);
|
|
}
|
|
else {
|
|
color = this.colors.getColor(d.d1);
|
|
}
|
|
}
|
|
else {
|
|
color = this.colors.getColor(seriesName);
|
|
}
|
|
const data = Object.assign({}, d, {
|
|
series: seriesName,
|
|
value,
|
|
name: label
|
|
});
|
|
return {
|
|
classNames: [`circle-data-${i}`],
|
|
value,
|
|
label,
|
|
data,
|
|
cx,
|
|
cy,
|
|
radius,
|
|
height,
|
|
tooltipLabel,
|
|
color,
|
|
opacity,
|
|
seriesName,
|
|
gradientStops: this.getGradientStops(color),
|
|
min: d.min,
|
|
max: d.max
|
|
};
|
|
}
|
|
getTooltipText({ tooltipLabel, value, seriesName, min, max }) {
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(seriesName)} • ${escapeLabel(tooltipLabel)}</span>
|
|
<span class="tooltip-val">${value.toLocaleString()}${this.getTooltipMinMaxText(min, max)}</span>
|
|
`;
|
|
}
|
|
getTooltipMinMaxText(min, max) {
|
|
if (min !== undefined || max !== undefined) {
|
|
let result = ' (';
|
|
if (min !== undefined) {
|
|
if (max === undefined) {
|
|
result += '≥';
|
|
}
|
|
result += min.toLocaleString();
|
|
if (max !== undefined) {
|
|
result += ' - ';
|
|
}
|
|
}
|
|
else if (max !== undefined) {
|
|
result += '≤';
|
|
}
|
|
if (max !== undefined) {
|
|
result += max.toLocaleString();
|
|
}
|
|
result += ')';
|
|
return result;
|
|
}
|
|
else {
|
|
return '';
|
|
}
|
|
}
|
|
getGradientStops(color) {
|
|
return [
|
|
{
|
|
offset: 0,
|
|
color,
|
|
opacity: 0.2
|
|
},
|
|
{
|
|
offset: 100,
|
|
color,
|
|
opacity: 1
|
|
}
|
|
];
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
activateCircle() {
|
|
this.barVisible = true;
|
|
this.activate.emit({ name: this.data.name });
|
|
}
|
|
deactivateCircle() {
|
|
this.barVisible = false;
|
|
this.circle.opacity = 0;
|
|
this.deactivate.emit({ name: this.data.name });
|
|
}
|
|
}
|
|
CircleSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CircleSeriesComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
CircleSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: CircleSeriesComponent, selector: "g[ngx-charts-circle-series]", inputs: { data: "data", type: "type", xScale: "xScale", yScale: "yScale", colors: "colors", scaleType: "scaleType", visibleValue: "visibleValue", activeEntries: "activeEntries", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g *ngIf="circle">
|
|
<defs>
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="circle.gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:rect
|
|
*ngIf="!isSSR && barVisible && type === 'standard'"
|
|
[@animationState]="'active'"
|
|
[attr.x]="circle.cx - circle.radius"
|
|
[attr.y]="circle.cy"
|
|
[attr.width]="circle.radius * 2"
|
|
[attr.height]="circle.height"
|
|
[attr.fill]="gradientFill"
|
|
class="tooltip-bar"
|
|
/>
|
|
<svg:rect
|
|
*ngIf="isSSR && barVisible && type === 'standard'"
|
|
[attr.x]="circle.cx - circle.radius"
|
|
[attr.y]="circle.cy"
|
|
[attr.width]="circle.radius * 2"
|
|
[attr.height]="circle.height"
|
|
[attr.fill]="gradientFill"
|
|
class="tooltip-bar"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-circle
|
|
class="circle"
|
|
[cx]="circle.cx"
|
|
[cy]="circle.cy"
|
|
[r]="circle.radius"
|
|
[fill]="circle.color"
|
|
[class.active]="isActive({ name: circle.seriesName })"
|
|
[pointerEvents]="circle.value === 0 ? 'none' : 'all'"
|
|
[data]="circle.value"
|
|
[classNames]="circle.classNames"
|
|
(select)="onClick(circle.data)"
|
|
(activate)="activateCircle()"
|
|
(deactivate)="deactivateCircle()"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }, { type: CircleComponent, selector: "g[ngx-charts-circle]", inputs: ["cx", "cy", "r", "fill", "stroke", "data", "classNames", "circleOpacity", "pointerEvents"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':enter', [
|
|
style({
|
|
opacity: 0
|
|
}),
|
|
animate(250, style({ opacity: 1 }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CircleSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-circle-series]',
|
|
template: `
|
|
<svg:g *ngIf="circle">
|
|
<defs>
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="circle.gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:rect
|
|
*ngIf="!isSSR && barVisible && type === 'standard'"
|
|
[@animationState]="'active'"
|
|
[attr.x]="circle.cx - circle.radius"
|
|
[attr.y]="circle.cy"
|
|
[attr.width]="circle.radius * 2"
|
|
[attr.height]="circle.height"
|
|
[attr.fill]="gradientFill"
|
|
class="tooltip-bar"
|
|
/>
|
|
<svg:rect
|
|
*ngIf="isSSR && barVisible && type === 'standard'"
|
|
[attr.x]="circle.cx - circle.radius"
|
|
[attr.y]="circle.cy"
|
|
[attr.width]="circle.radius * 2"
|
|
[attr.height]="circle.height"
|
|
[attr.fill]="gradientFill"
|
|
class="tooltip-bar"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-circle
|
|
class="circle"
|
|
[cx]="circle.cx"
|
|
[cy]="circle.cy"
|
|
[r]="circle.radius"
|
|
[fill]="circle.color"
|
|
[class.active]="isActive({ name: circle.seriesName })"
|
|
[pointerEvents]="circle.value === 0 ? 'none' : 'all'"
|
|
[data]="circle.value"
|
|
[classNames]="circle.classNames"
|
|
(select)="onClick(circle.data)"
|
|
(activate)="activateCircle()"
|
|
(deactivate)="deactivateCircle()"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition(':enter', [
|
|
style({
|
|
opacity: 0
|
|
}),
|
|
animate(250, style({ opacity: 1 }))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { data: [{
|
|
type: Input
|
|
}], type: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], scaleType: [{
|
|
type: Input
|
|
}], visibleValue: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class GridPanelComponent {
|
|
}
|
|
GridPanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GridPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
GridPanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: GridPanelComponent, selector: "g[ngx-charts-grid-panel]", inputs: { width: "width", height: "height", x: "x", y: "y" }, ngImport: i0, template: `
|
|
<svg:rect [attr.height]="height" [attr.width]="width" [attr.x]="x" [attr.y]="y" stroke="none" class="gridpanel" />
|
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GridPanelComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-grid-panel]',
|
|
template: `
|
|
<svg:rect [attr.height]="height" [attr.width]="width" [attr.x]="x" [attr.y]="y" stroke="none" class="gridpanel" />
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], x: [{
|
|
type: Input
|
|
}], y: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
var ClassEnum;
|
|
(function (ClassEnum) {
|
|
ClassEnum["Odd"] = "odd";
|
|
ClassEnum["Even"] = "even";
|
|
})(ClassEnum || (ClassEnum = {}));
|
|
class GridPanelSeriesComponent {
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.gridPanels = this.getGridPanels();
|
|
}
|
|
getGridPanels() {
|
|
return this.data.map(d => {
|
|
let offset;
|
|
let width;
|
|
let height;
|
|
let x;
|
|
let y;
|
|
let className = ClassEnum.Odd;
|
|
if (this.orient === BarOrientation.Vertical) {
|
|
const position = this.xScale(d.name);
|
|
const positionIndex = Number.parseInt((position / this.xScale.step()).toString(), 10);
|
|
if (positionIndex % 2 === 1) {
|
|
className = ClassEnum.Even;
|
|
}
|
|
offset = this.xScale.bandwidth() * this.xScale.paddingInner();
|
|
width = this.xScale.bandwidth() + offset;
|
|
height = this.dims.height;
|
|
x = this.xScale(d.name) - offset / 2;
|
|
y = 0;
|
|
}
|
|
else if (this.orient === BarOrientation.Horizontal) {
|
|
const position = this.yScale(d.name);
|
|
const positionIndex = Number.parseInt((position / this.yScale.step()).toString(), 10);
|
|
if (positionIndex % 2 === 1) {
|
|
className = ClassEnum.Even;
|
|
}
|
|
offset = this.yScale.bandwidth() * this.yScale.paddingInner();
|
|
width = this.dims.width;
|
|
height = this.yScale.bandwidth() + offset;
|
|
x = 0;
|
|
y = this.yScale(d.name) - offset / 2;
|
|
}
|
|
return {
|
|
name: d.name,
|
|
class: className,
|
|
height,
|
|
width,
|
|
x,
|
|
y
|
|
};
|
|
});
|
|
}
|
|
}
|
|
GridPanelSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GridPanelSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
GridPanelSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: GridPanelSeriesComponent, selector: "g[ngx-charts-grid-panel-series]", inputs: { data: "data", dims: "dims", xScale: "xScale", yScale: "yScale", orient: "orient" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-grid-panel
|
|
*ngFor="let gridPanel of gridPanels"
|
|
[height]="gridPanel.height"
|
|
[width]="gridPanel.width"
|
|
[x]="gridPanel.x"
|
|
[y]="gridPanel.y"
|
|
[class.grid-panel]="true"
|
|
[class.odd]="gridPanel.class === 'odd'"
|
|
[class.even]="gridPanel.class === 'even'"
|
|
></svg:g>
|
|
`, isInline: true, components: [{ type: GridPanelComponent, selector: "g[ngx-charts-grid-panel]", inputs: ["width", "height", "x", "y"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GridPanelSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-grid-panel-series]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-grid-panel
|
|
*ngFor="let gridPanel of gridPanels"
|
|
[height]="gridPanel.height"
|
|
[width]="gridPanel.width"
|
|
[x]="gridPanel.x"
|
|
[y]="gridPanel.y"
|
|
[class.grid-panel]="true"
|
|
[class.odd]="gridPanel.class === 'odd'"
|
|
[class.even]="gridPanel.class === 'even'"
|
|
></svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { data: [{
|
|
type: Input
|
|
}], dims: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], orient: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class SvgRadialGradientComponent {
|
|
constructor() {
|
|
this.endOpacity = 1;
|
|
this.cx = 0;
|
|
this.cy = 0;
|
|
}
|
|
get stops() {
|
|
return this.stopsInput || this.stopsDefault;
|
|
}
|
|
set stops(value) {
|
|
this.stopsInput = value;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.r = '30%';
|
|
if ('color' in changes || 'startOpacity' in changes || 'endOpacity' in changes) {
|
|
this.stopsDefault = [
|
|
{
|
|
offset: 0,
|
|
color: this.color,
|
|
opacity: this.startOpacity
|
|
},
|
|
{
|
|
offset: 100,
|
|
color: this.color,
|
|
opacity: this.endOpacity
|
|
}
|
|
];
|
|
}
|
|
}
|
|
}
|
|
SvgRadialGradientComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SvgRadialGradientComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
SvgRadialGradientComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: SvgRadialGradientComponent, selector: "g[ngx-charts-svg-radial-gradient]", inputs: { color: "color", name: "name", startOpacity: "startOpacity", endOpacity: "endOpacity", cx: "cx", cy: "cy", stops: "stops" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:radialGradient [id]="name" [attr.cx]="cx" [attr.cy]="cy" [attr.r]="r" gradientUnits="userSpaceOnUse">
|
|
<svg:stop
|
|
*ngFor="let stop of stops"
|
|
[attr.offset]="stop.offset + '%'"
|
|
[style.stop-color]="stop.color"
|
|
[style.stop-opacity]="stop.opacity"
|
|
/>
|
|
</svg:radialGradient>
|
|
`, isInline: true, directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SvgRadialGradientComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-svg-radial-gradient]',
|
|
template: `
|
|
<svg:radialGradient [id]="name" [attr.cx]="cx" [attr.cy]="cy" [attr.r]="r" gradientUnits="userSpaceOnUse">
|
|
<svg:stop
|
|
*ngFor="let stop of stops"
|
|
[attr.offset]="stop.offset + '%'"
|
|
[style.stop-color]="stop.color"
|
|
[style.stop-opacity]="stop.opacity"
|
|
/>
|
|
</svg:radialGradient>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { color: [{
|
|
type: Input
|
|
}], name: [{
|
|
type: Input
|
|
}], startOpacity: [{
|
|
type: Input
|
|
}], endOpacity: [{
|
|
type: Input
|
|
}], cx: [{
|
|
type: Input
|
|
}], cy: [{
|
|
type: Input
|
|
}], stops: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class AreaComponent {
|
|
constructor(element) {
|
|
this.opacity = 1;
|
|
this.startOpacity = 0.5;
|
|
this.endOpacity = 1;
|
|
this.gradient = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.animationsLoaded = false;
|
|
this.hasGradient = false;
|
|
this.barOrientation = BarOrientation;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges() {
|
|
this.update();
|
|
if (!this.animationsLoaded) {
|
|
this.loadAnimation();
|
|
this.animationsLoaded = true;
|
|
}
|
|
}
|
|
update() {
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientFill = `url(#${this.gradientId})`;
|
|
if (this.gradient || this.stops) {
|
|
this.gradientStops = this.getGradient();
|
|
this.hasGradient = true;
|
|
}
|
|
else {
|
|
this.hasGradient = false;
|
|
}
|
|
this.updatePathEl();
|
|
}
|
|
loadAnimation() {
|
|
this.areaPath = this.startingPath;
|
|
setTimeout(this.updatePathEl.bind(this), 100);
|
|
}
|
|
updatePathEl() {
|
|
const node = select(this.element).select('.area');
|
|
if (this.animations) {
|
|
node.transition().duration(750).attr('d', this.path);
|
|
}
|
|
else {
|
|
node.attr('d', this.path);
|
|
}
|
|
}
|
|
getGradient() {
|
|
if (this.stops) {
|
|
return this.stops;
|
|
}
|
|
return [
|
|
{
|
|
offset: 0,
|
|
color: this.fill,
|
|
opacity: this.startOpacity
|
|
},
|
|
{
|
|
offset: 100,
|
|
color: this.fill,
|
|
opacity: this.endOpacity
|
|
}
|
|
];
|
|
}
|
|
}
|
|
AreaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
AreaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AreaComponent, selector: "g[ngx-charts-area]", inputs: { data: "data", path: "path", startingPath: "startingPath", fill: "fill", opacity: "opacity", startOpacity: "startOpacity", endOpacity: "endOpacity", gradient: "gradient", stops: "stops", animations: "animations" }, outputs: { select: "select" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:defs *ngIf="gradient">
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</svg:defs>
|
|
<svg:path class="area" [attr.d]="areaPath" [attr.fill]="gradient ? gradientFill : fill" [style.opacity]="opacity" />
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-area]',
|
|
template: `
|
|
<svg:defs *ngIf="gradient">
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</svg:defs>
|
|
<svg:path class="area" [attr.d]="areaPath" [attr.fill]="gradient ? gradientFill : fill" [style.opacity]="opacity" />
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { data: [{
|
|
type: Input
|
|
}], path: [{
|
|
type: Input
|
|
}], startingPath: [{
|
|
type: Input
|
|
}], fill: [{
|
|
type: Input
|
|
}], opacity: [{
|
|
type: Input
|
|
}], startOpacity: [{
|
|
type: Input
|
|
}], endOpacity: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], stops: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
// Robert Penner's easeOutExpo
|
|
function easeOutExpo(t, b, c, d) {
|
|
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
|
|
}
|
|
/**
|
|
* Counts from a number to the end incrementally.
|
|
*/
|
|
function count(countFrom, countTo, countDecimals, countDuration, callback) {
|
|
const startVal = Number(countFrom);
|
|
const endVal = Number(countTo);
|
|
const countDown = startVal > endVal;
|
|
const decimals = Math.max(0, countDecimals);
|
|
const dec = Math.pow(10, decimals);
|
|
const duration = Number(countDuration) * 1000;
|
|
let startTime;
|
|
function runCount(timestamp) {
|
|
let frameVal;
|
|
const progress = timestamp - startTime;
|
|
if (countDown) {
|
|
frameVal = startVal - easeOutExpo(progress, 0, startVal - endVal, duration);
|
|
}
|
|
else {
|
|
frameVal = easeOutExpo(progress, startVal, endVal - startVal, duration);
|
|
}
|
|
if (countDown) {
|
|
frameVal = frameVal < endVal ? endVal : frameVal;
|
|
}
|
|
else {
|
|
frameVal = frameVal > endVal ? endVal : frameVal;
|
|
}
|
|
frameVal = Math.round(frameVal * dec) / dec;
|
|
const tick = progress < duration;
|
|
callback({
|
|
value: frameVal,
|
|
progress,
|
|
timestamp,
|
|
finished: !tick
|
|
});
|
|
if (tick) {
|
|
return requestAnimationFrame(val => runCount(val));
|
|
}
|
|
}
|
|
return requestAnimationFrame(timestamp => {
|
|
startTime = timestamp;
|
|
return runCount(timestamp);
|
|
});
|
|
}
|
|
/**
|
|
* Determine decimals places
|
|
*
|
|
* @export
|
|
*/
|
|
function decimalChecker(countTo) {
|
|
const endVal = Number(countTo);
|
|
if (endVal % 1 !== 0 && Math.abs(endVal) <= 10) {
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Count up component
|
|
*
|
|
* Loosely inspired by:
|
|
* - https://github.com/izupet/angular2-counto
|
|
* - https://inorganik.github.io/countUp.js/
|
|
*
|
|
* @export
|
|
*/
|
|
class CountUpDirective {
|
|
constructor(cd, element) {
|
|
this.cd = cd;
|
|
this.countDuration = 1;
|
|
this.countPrefix = '';
|
|
this.countSuffix = '';
|
|
this.countChange = new EventEmitter();
|
|
this.countFinish = new EventEmitter();
|
|
this.value = '';
|
|
this._countDecimals = 0;
|
|
this._countTo = 0;
|
|
this._countFrom = 0;
|
|
this.nativeElement = element.nativeElement;
|
|
}
|
|
set countDecimals(val) {
|
|
this._countDecimals = val;
|
|
}
|
|
get countDecimals() {
|
|
if (this._countDecimals)
|
|
return this._countDecimals;
|
|
return decimalChecker(this.countTo);
|
|
}
|
|
set countTo(val) {
|
|
this._countTo = parseFloat(val);
|
|
this.start();
|
|
}
|
|
get countTo() {
|
|
return this._countTo;
|
|
}
|
|
set countFrom(val) {
|
|
this._countFrom = parseFloat(val);
|
|
this.start();
|
|
}
|
|
get countFrom() {
|
|
return this._countFrom;
|
|
}
|
|
ngOnDestroy() {
|
|
cancelAnimationFrame(this.animationReq);
|
|
}
|
|
start() {
|
|
cancelAnimationFrame(this.animationReq);
|
|
const valueFormatting = this.valueFormatting || (value => `${this.countPrefix}${value.toLocaleString()}${this.countSuffix}`);
|
|
const callback = ({ value, progress, finished }) => {
|
|
this.value = valueFormatting(value);
|
|
this.cd.markForCheck();
|
|
if (!finished)
|
|
this.countChange.emit({ value: this.value, progress });
|
|
if (finished)
|
|
this.countFinish.emit({ value: this.value, progress });
|
|
};
|
|
this.animationReq = count(this.countFrom, this.countTo, this.countDecimals, this.countDuration, callback);
|
|
}
|
|
}
|
|
CountUpDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CountUpDirective, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
CountUpDirective.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: CountUpDirective, selector: "[ngx-charts-count-up]", inputs: { countDuration: "countDuration", countPrefix: "countPrefix", countSuffix: "countSuffix", valueFormatting: "valueFormatting", countDecimals: "countDecimals", countTo: "countTo", countFrom: "countFrom" }, outputs: { countChange: "countChange", countFinish: "countFinish" }, ngImport: i0, template: ` {{ value }} `, isInline: true });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CountUpDirective, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: '[ngx-charts-count-up]',
|
|
template: ` {{ value }} `
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { countDuration: [{
|
|
type: Input
|
|
}], countPrefix: [{
|
|
type: Input
|
|
}], countSuffix: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], countDecimals: [{
|
|
type: Input
|
|
}], countTo: [{
|
|
type: Input
|
|
}], countFrom: [{
|
|
type: Input
|
|
}], countChange: [{
|
|
type: Output
|
|
}], countFinish: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
// If we don't check whether 'window' and 'global' variables are defined,
|
|
// code will fail in browser/node with 'variable is undefined' error.
|
|
let root;
|
|
if (typeof window !== 'undefined') {
|
|
root = window;
|
|
}
|
|
else if (typeof global !== 'undefined') {
|
|
root = global;
|
|
}
|
|
// tslint:disable-next-line:variable-name
|
|
const MouseEvent = root.MouseEvent;
|
|
function createMouseEvent(name, bubbles = false, cancelable = true) {
|
|
// Calling new of an event does not work correctly on IE. The following is a tested workaround
|
|
// See https://stackoverflow.com/questions/27176983/dispatchevent-not-working-in-ie11
|
|
if (typeof MouseEvent === 'function') {
|
|
// Sane browsers
|
|
return new MouseEvent(name, { bubbles, cancelable });
|
|
}
|
|
else {
|
|
// IE
|
|
const event = document.createEvent('MouseEvent');
|
|
event.initEvent(name, bubbles, cancelable);
|
|
return event;
|
|
}
|
|
}
|
|
|
|
class TooltipArea {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.anchorOpacity = 0;
|
|
this.anchorPos = -1;
|
|
this.anchorValues = [];
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
this.showPercentage = false;
|
|
this.tooltipDisabled = false;
|
|
this.hover = new EventEmitter();
|
|
}
|
|
getValues(xVal) {
|
|
const results = [];
|
|
for (const group of this.results) {
|
|
const item = group.series.find(d => d.name.toString() === xVal.toString());
|
|
let groupName = group.name;
|
|
if (groupName instanceof Date) {
|
|
groupName = groupName.toLocaleDateString();
|
|
}
|
|
if (item) {
|
|
const label = item.name;
|
|
let val = item.value;
|
|
if (this.showPercentage) {
|
|
val = (item.d1 - item.d0).toFixed(2) + '%';
|
|
}
|
|
let color;
|
|
if (this.colors.scaleType === ScaleType.Linear) {
|
|
let v = val;
|
|
if (item.d1) {
|
|
v = item.d1;
|
|
}
|
|
color = this.colors.getColor(v);
|
|
}
|
|
else {
|
|
color = this.colors.getColor(group.name);
|
|
}
|
|
const data = Object.assign({}, item, {
|
|
value: val,
|
|
name: label,
|
|
series: groupName,
|
|
min: item.min,
|
|
max: item.max,
|
|
color
|
|
});
|
|
results.push(data);
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
mouseMove(event) {
|
|
if (!isPlatformBrowser(this.platformId)) {
|
|
return;
|
|
}
|
|
const xPos = event.pageX - event.target.getBoundingClientRect().left;
|
|
const closestIndex = this.findClosestPointIndex(xPos);
|
|
const closestPoint = this.xSet[closestIndex];
|
|
this.anchorPos = this.xScale(closestPoint);
|
|
this.anchorPos = Math.max(0, this.anchorPos);
|
|
this.anchorPos = Math.min(this.dims.width, this.anchorPos);
|
|
this.anchorValues = this.getValues(closestPoint);
|
|
if (this.anchorPos !== this.lastAnchorPos) {
|
|
const ev = createMouseEvent('mouseleave');
|
|
this.tooltipAnchor.nativeElement.dispatchEvent(ev);
|
|
this.anchorOpacity = 0.7;
|
|
this.hover.emit({
|
|
value: closestPoint
|
|
});
|
|
this.showTooltip();
|
|
this.lastAnchorPos = this.anchorPos;
|
|
}
|
|
}
|
|
findClosestPointIndex(xPos) {
|
|
let minIndex = 0;
|
|
let maxIndex = this.xSet.length - 1;
|
|
let minDiff = Number.MAX_VALUE;
|
|
let closestIndex = 0;
|
|
while (minIndex <= maxIndex) {
|
|
const currentIndex = ((minIndex + maxIndex) / 2) | 0;
|
|
const currentElement = this.xScale(this.xSet[currentIndex]);
|
|
const curDiff = Math.abs(currentElement - xPos);
|
|
if (curDiff < minDiff) {
|
|
minDiff = curDiff;
|
|
closestIndex = currentIndex;
|
|
}
|
|
if (currentElement < xPos) {
|
|
minIndex = currentIndex + 1;
|
|
}
|
|
else if (currentElement > xPos) {
|
|
maxIndex = currentIndex - 1;
|
|
}
|
|
else {
|
|
minDiff = 0;
|
|
closestIndex = currentIndex;
|
|
break;
|
|
}
|
|
}
|
|
return closestIndex;
|
|
}
|
|
showTooltip() {
|
|
const event = createMouseEvent('mouseenter');
|
|
this.tooltipAnchor.nativeElement.dispatchEvent(event);
|
|
}
|
|
hideTooltip() {
|
|
const event = createMouseEvent('mouseleave');
|
|
this.tooltipAnchor.nativeElement.dispatchEvent(event);
|
|
this.anchorOpacity = 0;
|
|
this.lastAnchorPos = -1;
|
|
}
|
|
getToolTipText(tooltipItem) {
|
|
let result = '';
|
|
if (tooltipItem.series !== undefined) {
|
|
result += tooltipItem.series;
|
|
}
|
|
else {
|
|
result += '???';
|
|
}
|
|
result += ': ';
|
|
if (tooltipItem.value !== undefined) {
|
|
result += tooltipItem.value.toLocaleString();
|
|
}
|
|
if (tooltipItem.min !== undefined || tooltipItem.max !== undefined) {
|
|
result += ' (';
|
|
if (tooltipItem.min !== undefined) {
|
|
if (tooltipItem.max === undefined) {
|
|
result += '≥';
|
|
}
|
|
result += tooltipItem.min.toLocaleString();
|
|
if (tooltipItem.max !== undefined) {
|
|
result += ' - ';
|
|
}
|
|
}
|
|
else if (tooltipItem.max !== undefined) {
|
|
result += '≤';
|
|
}
|
|
if (tooltipItem.max !== undefined) {
|
|
result += tooltipItem.max.toLocaleString();
|
|
}
|
|
result += ')';
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
TooltipArea.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipArea, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
TooltipArea.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: TooltipArea, selector: "g[ngx-charts-tooltip-area]", inputs: { dims: "dims", xSet: "xSet", xScale: "xScale", yScale: "yScale", results: "results", colors: "colors", showPercentage: "showPercentage", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate" }, outputs: { hover: "hover" }, viewQueries: [{ propertyName: "tooltipAnchor", first: true, predicate: ["tooltipAnchor"], descendants: true }], ngImport: i0, template: `
|
|
<svg:g>
|
|
<svg:rect
|
|
class="tooltip-area"
|
|
[attr.x]="0"
|
|
y="0"
|
|
[attr.width]="dims.width"
|
|
[attr.height]="dims.height"
|
|
style="opacity: 0; cursor: 'auto';"
|
|
(mousemove)="mouseMove($event)"
|
|
(mouseleave)="hideTooltip()"
|
|
/>
|
|
<ng-template #defaultTooltipTemplate let-model="model">
|
|
<xhtml:div class="area-tooltip-container">
|
|
<xhtml:div *ngFor="let tooltipItem of model" class="tooltip-item">
|
|
<xhtml:span class="tooltip-item-color" [style.background-color]="tooltipItem.color"></xhtml:span>
|
|
{{ getToolTipText(tooltipItem) }}
|
|
</xhtml:div>
|
|
</xhtml:div>
|
|
</ng-template>
|
|
<svg:rect
|
|
#tooltipAnchor
|
|
[@animationState]="anchorOpacity !== 0 ? 'active' : 'inactive'"
|
|
class="tooltip-anchor"
|
|
[attr.x]="anchorPos"
|
|
y="0"
|
|
[attr.width]="1"
|
|
[attr.height]="dims.height"
|
|
[style.opacity]="anchorOpacity"
|
|
[style.pointer-events]="'none'"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Right"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipSpacing]="15"
|
|
[tooltipTemplate]="tooltipTemplate ? tooltipTemplate : defaultTooltipTemplate"
|
|
[tooltipContext]="anchorValues"
|
|
[tooltipImmediateExit]="true"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], animations: [
|
|
trigger('animationState', [
|
|
transition('inactive => active', [
|
|
style({
|
|
opacity: 0
|
|
}),
|
|
animate(250, style({ opacity: 0.7 }))
|
|
]),
|
|
transition('active => inactive', [
|
|
style({
|
|
opacity: 0.7
|
|
}),
|
|
animate(250, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TooltipArea, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-tooltip-area]',
|
|
template: `
|
|
<svg:g>
|
|
<svg:rect
|
|
class="tooltip-area"
|
|
[attr.x]="0"
|
|
y="0"
|
|
[attr.width]="dims.width"
|
|
[attr.height]="dims.height"
|
|
style="opacity: 0; cursor: 'auto';"
|
|
(mousemove)="mouseMove($event)"
|
|
(mouseleave)="hideTooltip()"
|
|
/>
|
|
<ng-template #defaultTooltipTemplate let-model="model">
|
|
<xhtml:div class="area-tooltip-container">
|
|
<xhtml:div *ngFor="let tooltipItem of model" class="tooltip-item">
|
|
<xhtml:span class="tooltip-item-color" [style.background-color]="tooltipItem.color"></xhtml:span>
|
|
{{ getToolTipText(tooltipItem) }}
|
|
</xhtml:div>
|
|
</xhtml:div>
|
|
</ng-template>
|
|
<svg:rect
|
|
#tooltipAnchor
|
|
[@animationState]="anchorOpacity !== 0 ? 'active' : 'inactive'"
|
|
class="tooltip-anchor"
|
|
[attr.x]="anchorPos"
|
|
y="0"
|
|
[attr.width]="1"
|
|
[attr.height]="dims.height"
|
|
[style.opacity]="anchorOpacity"
|
|
[style.pointer-events]="'none'"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Right"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipSpacing]="15"
|
|
[tooltipTemplate]="tooltipTemplate ? tooltipTemplate : defaultTooltipTemplate"
|
|
[tooltipContext]="anchorValues"
|
|
[tooltipImmediateExit]="true"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition('inactive => active', [
|
|
style({
|
|
opacity: 0
|
|
}),
|
|
animate(250, style({ opacity: 0.7 }))
|
|
]),
|
|
transition('active => inactive', [
|
|
style({
|
|
opacity: 0.7
|
|
}),
|
|
animate(250, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { dims: [{
|
|
type: Input
|
|
}], xSet: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], results: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], showPercentage: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], hover: [{
|
|
type: Output
|
|
}], tooltipAnchor: [{
|
|
type: ViewChild,
|
|
args: ['tooltipAnchor', { static: false }]
|
|
}] } });
|
|
|
|
class Timeline {
|
|
constructor(element, cd) {
|
|
this.cd = cd;
|
|
this.height = 50;
|
|
this.select = new EventEmitter();
|
|
this.onDomainChange = new EventEmitter();
|
|
this.initialized = false;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
if (!this.initialized) {
|
|
this.addBrush();
|
|
this.initialized = true;
|
|
}
|
|
}
|
|
update() {
|
|
this.dims = this.getDims();
|
|
this.height = this.dims.height;
|
|
const offsetY = this.view[1] - this.height;
|
|
this.xDomain = this.getXDomain();
|
|
this.xScale = this.getXScale();
|
|
if (this.brush) {
|
|
this.updateBrush();
|
|
}
|
|
this.transform = `translate(0 , ${offsetY})`;
|
|
this.filterId = 'filter' + id().toString();
|
|
this.filter = `url(#${this.filterId})`;
|
|
this.cd.markForCheck();
|
|
}
|
|
getXDomain() {
|
|
let values = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (!values.includes(d.name)) {
|
|
values.push(d.name);
|
|
}
|
|
}
|
|
}
|
|
let domain = [];
|
|
if (this.scaleType === ScaleType.Time) {
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
domain = [min, max];
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
domain = [min, max];
|
|
}
|
|
else {
|
|
domain = values;
|
|
}
|
|
return domain;
|
|
}
|
|
getXScale() {
|
|
let scale;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
scale = scaleTime().range([0, this.dims.width]).domain(this.xDomain);
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
scale = scaleLinear().range([0, this.dims.width]).domain(this.xDomain);
|
|
}
|
|
else if (this.scaleType === ScaleType.Ordinal) {
|
|
scale = scalePoint().range([0, this.dims.width]).padding(0.1).domain(this.xDomain);
|
|
}
|
|
return scale;
|
|
}
|
|
addBrush() {
|
|
if (this.brush)
|
|
return;
|
|
const height = this.height;
|
|
const width = this.view[0];
|
|
this.brush = brushX()
|
|
.extent([
|
|
[0, 0],
|
|
[width, height]
|
|
])
|
|
.on('brush end', ({ selection }) => {
|
|
const newSelection = selection || this.xScale.range();
|
|
const newDomain = newSelection.map(this.xScale.invert);
|
|
this.onDomainChange.emit(newDomain);
|
|
this.cd.markForCheck();
|
|
});
|
|
select(this.element).select('.brush').call(this.brush);
|
|
}
|
|
updateBrush() {
|
|
if (!this.brush)
|
|
return;
|
|
const height = this.height;
|
|
const width = this.view[0];
|
|
this.brush.extent([
|
|
[0, 0],
|
|
[width, height]
|
|
]);
|
|
select(this.element).select('.brush').call(this.brush);
|
|
// clear hardcoded properties so they can be defined by CSS
|
|
select(this.element)
|
|
.select('.selection')
|
|
.attr('fill', undefined)
|
|
.attr('stroke', undefined)
|
|
.attr('fill-opacity', undefined);
|
|
this.cd.markForCheck();
|
|
}
|
|
getDims() {
|
|
const width = this.view[0];
|
|
const dims = {
|
|
width,
|
|
height: this.height
|
|
};
|
|
return dims;
|
|
}
|
|
}
|
|
Timeline.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: Timeline, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
Timeline.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: Timeline, selector: "g[ngx-charts-timeline]", inputs: { view: "view", results: "results", scheme: "scheme", customColors: "customColors", legend: "legend", autoScale: "autoScale", scaleType: "scaleType", height: "height" }, outputs: { select: "select", onDomainChange: "onDomainChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g class="timeline" [attr.transform]="transform">
|
|
<svg:filter [attr.id]="filterId">
|
|
<svg:feColorMatrix
|
|
in="SourceGraphic"
|
|
type="matrix"
|
|
values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"
|
|
/>
|
|
</svg:filter>
|
|
<svg:g class="embedded-chart">
|
|
<ng-content></ng-content>
|
|
</svg:g>
|
|
<svg:rect x="0" [attr.width]="view[0]" y="0" [attr.height]="height" class="brush-background" />
|
|
<svg:g class="brush"></svg:g>
|
|
</svg:g>
|
|
`, isInline: true, styles: [".timeline .brush-background{fill:#0000000d}.timeline .brush .selection{fill:#0000001a;stroke-width:1px;stroke:#888}.timeline .brush .handle{fill-opacity:0}.timeline .embedded-chart{opacity:.6}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: Timeline, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'g[ngx-charts-timeline]', template: `
|
|
<svg:g class="timeline" [attr.transform]="transform">
|
|
<svg:filter [attr.id]="filterId">
|
|
<svg:feColorMatrix
|
|
in="SourceGraphic"
|
|
type="matrix"
|
|
values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"
|
|
/>
|
|
</svg:filter>
|
|
<svg:g class="embedded-chart">
|
|
<ng-content></ng-content>
|
|
</svg:g>
|
|
<svg:rect x="0" [attr.width]="view[0]" y="0" [attr.height]="height" class="brush-background" />
|
|
<svg:g class="brush"></svg:g>
|
|
</svg:g>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".timeline .brush-background{fill:#0000000d}.timeline .brush .selection{fill:#0000001a;stroke-width:1px;stroke:#888}.timeline .brush .handle{fill-opacity:0}.timeline .embedded-chart{opacity:.6}\n"] }]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { view: [{
|
|
type: Input
|
|
}], results: [{
|
|
type: Input
|
|
}], scheme: [{
|
|
type: Input
|
|
}], customColors: [{
|
|
type: Input
|
|
}], legend: [{
|
|
type: Input
|
|
}], autoScale: [{
|
|
type: Input
|
|
}], scaleType: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], onDomainChange: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class AdvancedLegendComponent {
|
|
constructor() {
|
|
this.label = 'Total';
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.legendItems = [];
|
|
this.labelFormatting = label => label;
|
|
this.percentageFormatting = percentage => percentage;
|
|
this.defaultValueFormatting = value => value.toLocaleString();
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
getTotal() {
|
|
return this.data.map(d => Number(d.value)).reduce((sum, d) => sum + d, 0);
|
|
}
|
|
update() {
|
|
this.total = this.getTotal();
|
|
this.roundedTotal = this.total;
|
|
this.legendItems = this.getLegendItems();
|
|
}
|
|
getLegendItems() {
|
|
return this.data.map(d => {
|
|
const label = formatLabel(d.name);
|
|
const value = d.value;
|
|
const color = this.colors.getColor(label);
|
|
const percentage = this.total > 0 ? (value / this.total) * 100 : 0;
|
|
const formattedLabel = typeof this.labelFormatting === 'function' ? this.labelFormatting(label) : label;
|
|
return {
|
|
_value: value,
|
|
data: d,
|
|
value,
|
|
color,
|
|
label: formattedLabel,
|
|
displayLabel: trimLabel(formattedLabel, 20),
|
|
origialLabel: d.name,
|
|
percentage: this.percentageFormatting ? this.percentageFormatting(percentage) : percentage.toLocaleString()
|
|
};
|
|
});
|
|
}
|
|
trackBy(index, item) {
|
|
return item.label;
|
|
}
|
|
}
|
|
AdvancedLegendComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AdvancedLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
AdvancedLegendComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AdvancedLegendComponent, selector: "ngx-charts-advanced-legend", inputs: { width: "width", data: "data", colors: "colors", label: "label", animations: "animations", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", percentageFormatting: "percentageFormatting" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<div class="advanced-pie-legend" [style.width.px]="width">
|
|
<div
|
|
*ngIf="animations"
|
|
class="total-value"
|
|
ngx-charts-count-up
|
|
[countTo]="roundedTotal"
|
|
[valueFormatting]="valueFormatting"
|
|
></div>
|
|
<div class="total-value" *ngIf="!animations">
|
|
{{ valueFormatting ? valueFormatting(roundedTotal) : defaultValueFormatting(roundedTotal) }}
|
|
</div>
|
|
<div class="total-label">
|
|
{{ label }}
|
|
</div>
|
|
<div class="legend-items-container">
|
|
<div class="legend-items">
|
|
<div
|
|
*ngFor="let legendItem of legendItems; trackBy: trackBy"
|
|
tabindex="-1"
|
|
class="legend-item"
|
|
(mouseenter)="activate.emit(legendItem.data)"
|
|
(mouseleave)="deactivate.emit(legendItem.data)"
|
|
(click)="select.emit(legendItem.data)"
|
|
>
|
|
<div class="item-color" [style.border-left-color]="legendItem.color"></div>
|
|
<div
|
|
*ngIf="animations"
|
|
class="item-value"
|
|
ngx-charts-count-up
|
|
[countTo]="legendItem._value"
|
|
[valueFormatting]="valueFormatting"
|
|
></div>
|
|
<div *ngIf="!animations" class="item-value">
|
|
{{ valueFormatting ? valueFormatting(legendItem.value) : defaultValueFormatting(legendItem.value) }}
|
|
</div>
|
|
<div class="item-label">{{ legendItem.displayLabel }}</div>
|
|
<div
|
|
*ngIf="animations"
|
|
class="item-percent"
|
|
ngx-charts-count-up
|
|
[countTo]="legendItem.percentage"
|
|
[countSuffix]="'%'"
|
|
></div>
|
|
<div *ngIf="!animations" class="item-percent">{{ legendItem.percentage.toLocaleString() }}%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`, isInline: true, styles: [".advanced-pie-legend{float:left;position:relative;top:50%;transform:translateY(-50%)}.advanced-pie-legend .total-value{font-size:36px}.advanced-pie-legend .total-label{font-size:24px;margin-bottom:19px}.advanced-pie-legend .legend-items-container{width:100%}.advanced-pie-legend .legend-items-container .legend-items{white-space:nowrap;overflow:auto}.advanced-pie-legend .legend-items-container .legend-items .legend-item{margin-right:20px;display:inline-block;cursor:pointer}.advanced-pie-legend .legend-items-container .legend-items .legend-item:focus{outline:none}.advanced-pie-legend .legend-items-container .legend-items .legend-item:hover{color:#000;transition:.2s}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-value{font-size:24px;margin-top:-6px;margin-left:11px}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-label{font-size:14px;opacity:.7;margin-left:11px;margin-top:-6px}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-percent{font-size:24px;opacity:.7;margin-left:11px}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-color{border-left:4px solid;width:4px;height:42px;float:left;margin-right:7px}\n"], components: [{ type: CountUpDirective, selector: "[ngx-charts-count-up]", inputs: ["countDuration", "countPrefix", "countSuffix", "valueFormatting", "countDecimals", "countTo", "countFrom"], outputs: ["countChange", "countFinish"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AdvancedLegendComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-advanced-legend', template: `
|
|
<div class="advanced-pie-legend" [style.width.px]="width">
|
|
<div
|
|
*ngIf="animations"
|
|
class="total-value"
|
|
ngx-charts-count-up
|
|
[countTo]="roundedTotal"
|
|
[valueFormatting]="valueFormatting"
|
|
></div>
|
|
<div class="total-value" *ngIf="!animations">
|
|
{{ valueFormatting ? valueFormatting(roundedTotal) : defaultValueFormatting(roundedTotal) }}
|
|
</div>
|
|
<div class="total-label">
|
|
{{ label }}
|
|
</div>
|
|
<div class="legend-items-container">
|
|
<div class="legend-items">
|
|
<div
|
|
*ngFor="let legendItem of legendItems; trackBy: trackBy"
|
|
tabindex="-1"
|
|
class="legend-item"
|
|
(mouseenter)="activate.emit(legendItem.data)"
|
|
(mouseleave)="deactivate.emit(legendItem.data)"
|
|
(click)="select.emit(legendItem.data)"
|
|
>
|
|
<div class="item-color" [style.border-left-color]="legendItem.color"></div>
|
|
<div
|
|
*ngIf="animations"
|
|
class="item-value"
|
|
ngx-charts-count-up
|
|
[countTo]="legendItem._value"
|
|
[valueFormatting]="valueFormatting"
|
|
></div>
|
|
<div *ngIf="!animations" class="item-value">
|
|
{{ valueFormatting ? valueFormatting(legendItem.value) : defaultValueFormatting(legendItem.value) }}
|
|
</div>
|
|
<div class="item-label">{{ legendItem.displayLabel }}</div>
|
|
<div
|
|
*ngIf="animations"
|
|
class="item-percent"
|
|
ngx-charts-count-up
|
|
[countTo]="legendItem.percentage"
|
|
[countSuffix]="'%'"
|
|
></div>
|
|
<div *ngIf="!animations" class="item-percent">{{ legendItem.percentage.toLocaleString() }}%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".advanced-pie-legend{float:left;position:relative;top:50%;transform:translateY(-50%)}.advanced-pie-legend .total-value{font-size:36px}.advanced-pie-legend .total-label{font-size:24px;margin-bottom:19px}.advanced-pie-legend .legend-items-container{width:100%}.advanced-pie-legend .legend-items-container .legend-items{white-space:nowrap;overflow:auto}.advanced-pie-legend .legend-items-container .legend-items .legend-item{margin-right:20px;display:inline-block;cursor:pointer}.advanced-pie-legend .legend-items-container .legend-items .legend-item:focus{outline:none}.advanced-pie-legend .legend-items-container .legend-items .legend-item:hover{color:#000;transition:.2s}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-value{font-size:24px;margin-top:-6px;margin-left:11px}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-label{font-size:14px;opacity:.7;margin-left:11px;margin-top:-6px}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-percent{font-size:24px;opacity:.7;margin-left:11px}.advanced-pie-legend .legend-items-container .legend-items .legend-item .item-color{border-left:4px solid;width:4px;height:42px;float:left;margin-right:7px}\n"] }]
|
|
}], propDecorators: { width: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], percentageFormatting: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
const COMPONENTS = [
|
|
AreaComponent,
|
|
BaseChartComponent,
|
|
CountUpDirective,
|
|
TooltipArea,
|
|
ChartComponent,
|
|
LegendComponent,
|
|
LegendEntryComponent,
|
|
ScaleLegendComponent,
|
|
CircleComponent,
|
|
CircleSeriesComponent,
|
|
GridPanelComponent,
|
|
GridPanelSeriesComponent,
|
|
SvgLinearGradientComponent,
|
|
SvgRadialGradientComponent,
|
|
Timeline,
|
|
AdvancedLegendComponent
|
|
];
|
|
class ChartCommonModule {
|
|
}
|
|
ChartCommonModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ChartCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
ChartCommonModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ChartCommonModule, declarations: [AreaComponent,
|
|
BaseChartComponent,
|
|
CountUpDirective,
|
|
TooltipArea,
|
|
ChartComponent,
|
|
LegendComponent,
|
|
LegendEntryComponent,
|
|
ScaleLegendComponent,
|
|
CircleComponent,
|
|
CircleSeriesComponent,
|
|
GridPanelComponent,
|
|
GridPanelSeriesComponent,
|
|
SvgLinearGradientComponent,
|
|
SvgRadialGradientComponent,
|
|
Timeline,
|
|
AdvancedLegendComponent, VisibilityObserver], imports: [CommonModule, AxesModule, TooltipModule], exports: [CommonModule, AxesModule, TooltipModule, AreaComponent,
|
|
BaseChartComponent,
|
|
CountUpDirective,
|
|
TooltipArea,
|
|
ChartComponent,
|
|
LegendComponent,
|
|
LegendEntryComponent,
|
|
ScaleLegendComponent,
|
|
CircleComponent,
|
|
CircleSeriesComponent,
|
|
GridPanelComponent,
|
|
GridPanelSeriesComponent,
|
|
SvgLinearGradientComponent,
|
|
SvgRadialGradientComponent,
|
|
Timeline,
|
|
AdvancedLegendComponent, VisibilityObserver] });
|
|
ChartCommonModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ChartCommonModule, imports: [[CommonModule, AxesModule, TooltipModule], CommonModule, AxesModule, TooltipModule] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: ChartCommonModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [CommonModule, AxesModule, TooltipModule],
|
|
declarations: [...COMPONENTS, VisibilityObserver],
|
|
exports: [CommonModule, AxesModule, TooltipModule, ...COMPONENTS, VisibilityObserver]
|
|
}]
|
|
}] });
|
|
|
|
function calculateViewDimensions({ width, height, margins, showXAxis = false, showYAxis = false, xAxisHeight = 0, yAxisWidth = 0, showXLabel = false, showYLabel = false, showLegend = false, legendType = ScaleType.Ordinal, legendPosition = LegendPosition.Right, columns = 12 }) {
|
|
let xOffset = margins[3];
|
|
let chartWidth = width;
|
|
let chartHeight = height - margins[0] - margins[2];
|
|
if (showLegend && legendPosition === LegendPosition.Right) {
|
|
if (legendType === ScaleType.Ordinal) {
|
|
columns -= 2;
|
|
}
|
|
else {
|
|
columns -= 1;
|
|
}
|
|
}
|
|
chartWidth = (chartWidth * columns) / 12;
|
|
chartWidth = chartWidth - margins[1] - margins[3];
|
|
if (showXAxis) {
|
|
chartHeight -= 5;
|
|
chartHeight -= xAxisHeight;
|
|
if (showXLabel) {
|
|
// text height + spacing between axis label and tick labels
|
|
const offset = 25 + 5;
|
|
chartHeight -= offset;
|
|
}
|
|
}
|
|
if (showYAxis) {
|
|
chartWidth -= 5;
|
|
chartWidth -= yAxisWidth;
|
|
xOffset += yAxisWidth;
|
|
xOffset += 10;
|
|
if (showYLabel) {
|
|
// text height + spacing between axis label and tick labels
|
|
const offset = 25 + 5;
|
|
chartWidth -= offset;
|
|
xOffset += offset;
|
|
}
|
|
}
|
|
chartWidth = Math.max(0, chartWidth);
|
|
chartHeight = Math.max(0, chartHeight);
|
|
return {
|
|
width: Math.floor(chartWidth),
|
|
height: Math.floor(chartHeight),
|
|
xOffset: Math.floor(xOffset)
|
|
};
|
|
}
|
|
|
|
const colorSets = [
|
|
{
|
|
name: 'vivid',
|
|
selectable: true,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#647c8a',
|
|
'#3f51b5',
|
|
'#2196f3',
|
|
'#00b862',
|
|
'#afdf0a',
|
|
'#a7b61a',
|
|
'#f3e562',
|
|
'#ff9800',
|
|
'#ff5722',
|
|
'#ff4514'
|
|
]
|
|
},
|
|
{
|
|
name: 'natural',
|
|
selectable: true,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#bf9d76',
|
|
'#e99450',
|
|
'#d89f59',
|
|
'#f2dfa7',
|
|
'#a5d7c6',
|
|
'#7794b1',
|
|
'#afafaf',
|
|
'#707160',
|
|
'#ba9383',
|
|
'#d9d5c3'
|
|
]
|
|
},
|
|
{
|
|
name: 'cool',
|
|
selectable: true,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#a8385d',
|
|
'#7aa3e5',
|
|
'#a27ea8',
|
|
'#aae3f5',
|
|
'#adcded',
|
|
'#a95963',
|
|
'#8796c0',
|
|
'#7ed3ed',
|
|
'#50abcc',
|
|
'#ad6886'
|
|
]
|
|
},
|
|
{
|
|
name: 'fire',
|
|
selectable: true,
|
|
group: ScaleType.Ordinal,
|
|
domain: ['#ff3d00', '#bf360c', '#ff8f00', '#ff6f00', '#ff5722', '#e65100', '#ffca28', '#ffab00']
|
|
},
|
|
{
|
|
name: 'solar',
|
|
selectable: true,
|
|
group: ScaleType.Linear,
|
|
domain: [
|
|
'#fff8e1',
|
|
'#ffecb3',
|
|
'#ffe082',
|
|
'#ffd54f',
|
|
'#ffca28',
|
|
'#ffc107',
|
|
'#ffb300',
|
|
'#ffa000',
|
|
'#ff8f00',
|
|
'#ff6f00'
|
|
]
|
|
},
|
|
{
|
|
name: 'air',
|
|
selectable: true,
|
|
group: ScaleType.Linear,
|
|
domain: [
|
|
'#e1f5fe',
|
|
'#b3e5fc',
|
|
'#81d4fa',
|
|
'#4fc3f7',
|
|
'#29b6f6',
|
|
'#03a9f4',
|
|
'#039be5',
|
|
'#0288d1',
|
|
'#0277bd',
|
|
'#01579b'
|
|
]
|
|
},
|
|
{
|
|
name: 'aqua',
|
|
selectable: true,
|
|
group: ScaleType.Linear,
|
|
domain: [
|
|
'#e0f7fa',
|
|
'#b2ebf2',
|
|
'#80deea',
|
|
'#4dd0e1',
|
|
'#26c6da',
|
|
'#00bcd4',
|
|
'#00acc1',
|
|
'#0097a7',
|
|
'#00838f',
|
|
'#006064'
|
|
]
|
|
},
|
|
{
|
|
name: 'flame',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#A10A28',
|
|
'#D3342D',
|
|
'#EF6D49',
|
|
'#FAAD67',
|
|
'#FDDE90',
|
|
'#DBED91',
|
|
'#A9D770',
|
|
'#6CBA67',
|
|
'#2C9653',
|
|
'#146738'
|
|
]
|
|
},
|
|
{
|
|
name: 'ocean',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#1D68FB',
|
|
'#33C0FC',
|
|
'#4AFFFE',
|
|
'#AFFFFF',
|
|
'#FFFC63',
|
|
'#FDBD2D',
|
|
'#FC8A25',
|
|
'#FA4F1E',
|
|
'#FA141B',
|
|
'#BA38D1'
|
|
]
|
|
},
|
|
{
|
|
name: 'forest',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#55C22D',
|
|
'#C1F33D',
|
|
'#3CC099',
|
|
'#AFFFFF',
|
|
'#8CFC9D',
|
|
'#76CFFA',
|
|
'#BA60FB',
|
|
'#EE6490',
|
|
'#C42A1C',
|
|
'#FC9F32'
|
|
]
|
|
},
|
|
{
|
|
name: 'horizon',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#2597FB',
|
|
'#65EBFD',
|
|
'#99FDD0',
|
|
'#FCEE4B',
|
|
'#FEFCFA',
|
|
'#FDD6E3',
|
|
'#FCB1A8',
|
|
'#EF6F7B',
|
|
'#CB96E8',
|
|
'#EFDEE0'
|
|
]
|
|
},
|
|
{
|
|
name: 'neons',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#FF3333',
|
|
'#FF33FF',
|
|
'#CC33FF',
|
|
'#0000FF',
|
|
'#33CCFF',
|
|
'#33FFFF',
|
|
'#33FF66',
|
|
'#CCFF33',
|
|
'#FFCC00',
|
|
'#FF6600'
|
|
]
|
|
},
|
|
{
|
|
name: 'picnic',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#FAC51D',
|
|
'#66BD6D',
|
|
'#FAA026',
|
|
'#29BB9C',
|
|
'#E96B56',
|
|
'#55ACD2',
|
|
'#B7332F',
|
|
'#2C83C9',
|
|
'#9166B8',
|
|
'#92E7E8'
|
|
]
|
|
},
|
|
{
|
|
name: 'night',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#2B1B5A',
|
|
'#501356',
|
|
'#183356',
|
|
'#28203F',
|
|
'#391B3C',
|
|
'#1E2B3C',
|
|
'#120634',
|
|
'#2D0432',
|
|
'#051932',
|
|
'#453080',
|
|
'#75267D',
|
|
'#2C507D',
|
|
'#4B3880',
|
|
'#752F7D',
|
|
'#35547D'
|
|
]
|
|
},
|
|
{
|
|
name: 'nightLights',
|
|
selectable: false,
|
|
group: ScaleType.Ordinal,
|
|
domain: [
|
|
'#4e31a5',
|
|
'#9c25a7',
|
|
'#3065ab',
|
|
'#57468b',
|
|
'#904497',
|
|
'#46648b',
|
|
'#32118d',
|
|
'#a00fb3',
|
|
'#1052a2',
|
|
'#6e51bd',
|
|
'#b63cc3',
|
|
'#6c97cb',
|
|
'#8671c1',
|
|
'#b455be',
|
|
'#7496c3'
|
|
]
|
|
}
|
|
];
|
|
|
|
class ColorHelper {
|
|
constructor(scheme, type, domain, customColors) {
|
|
if (typeof scheme === 'string') {
|
|
scheme = colorSets.find(cs => {
|
|
return cs.name === scheme;
|
|
});
|
|
}
|
|
this.colorDomain = scheme.domain;
|
|
this.scaleType = type;
|
|
this.domain = domain;
|
|
this.customColors = customColors;
|
|
this.scale = this.generateColorScheme(scheme, type, this.domain);
|
|
}
|
|
generateColorScheme(scheme, type, domain) {
|
|
if (typeof scheme === 'string') {
|
|
scheme = colorSets.find(cs => {
|
|
return cs.name === scheme;
|
|
});
|
|
}
|
|
let colorScale;
|
|
switch (type) {
|
|
case ScaleType.Quantile:
|
|
colorScale = scaleQuantile()
|
|
.range(scheme.domain)
|
|
.domain(domain);
|
|
break;
|
|
case ScaleType.Ordinal:
|
|
colorScale = scaleOrdinal()
|
|
.range(scheme.domain)
|
|
.domain(domain);
|
|
break;
|
|
case ScaleType.Linear:
|
|
{
|
|
const colorDomain = [...scheme.domain];
|
|
if (colorDomain.length === 1) {
|
|
colorDomain.push(colorDomain[0]);
|
|
this.colorDomain = colorDomain;
|
|
}
|
|
const points = range(0, 1, 1.0 / colorDomain.length);
|
|
colorScale = scaleLinear()
|
|
.range(colorDomain)
|
|
.domain(points);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return colorScale;
|
|
}
|
|
getColor(value) {
|
|
if (value === undefined || value === null) {
|
|
throw new Error('Value can not be null');
|
|
}
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
const valueScale = scaleLinear()
|
|
.domain(this.domain)
|
|
.range([0, 1]);
|
|
return this.scale(valueScale(value));
|
|
}
|
|
else {
|
|
if (typeof this.customColors === 'function') {
|
|
return this.customColors(value);
|
|
}
|
|
const formattedValue = value.toString();
|
|
let found; // todo type customColors
|
|
if (this.customColors && this.customColors.length > 0) {
|
|
found = this.customColors.find(mapping => {
|
|
return mapping.name.toLowerCase() === formattedValue.toLowerCase();
|
|
});
|
|
}
|
|
if (found) {
|
|
return found.value;
|
|
}
|
|
else {
|
|
return this.scale(value);
|
|
}
|
|
}
|
|
}
|
|
getLinearGradientStops(value, start) {
|
|
if (start === undefined) {
|
|
start = this.domain[0];
|
|
}
|
|
const valueScale = scaleLinear()
|
|
.domain(this.domain)
|
|
.range([0, 1]);
|
|
const colorValueScale = scaleBand().domain(this.colorDomain).range([0, 1]);
|
|
const endColor = this.getColor(value);
|
|
// generate the stops
|
|
const startVal = valueScale(start);
|
|
const startColor = this.getColor(start);
|
|
const endVal = valueScale(value);
|
|
let i = 1;
|
|
let currentVal = startVal;
|
|
const stops = [];
|
|
stops.push({
|
|
color: startColor,
|
|
offset: startVal,
|
|
originalOffset: startVal,
|
|
opacity: 1
|
|
});
|
|
while (currentVal < endVal && i < this.colorDomain.length) {
|
|
const color = this.colorDomain[i];
|
|
const offset = colorValueScale(color);
|
|
if (offset <= startVal) {
|
|
i++;
|
|
continue;
|
|
}
|
|
if (offset.toFixed(4) >= (endVal - colorValueScale.bandwidth()).toFixed(4)) {
|
|
break;
|
|
}
|
|
stops.push({
|
|
color,
|
|
offset,
|
|
opacity: 1
|
|
});
|
|
currentVal = offset;
|
|
i++;
|
|
}
|
|
if (stops[stops.length - 1].offset < 100) {
|
|
stops.push({
|
|
color: endColor,
|
|
offset: endVal,
|
|
opacity: 1
|
|
});
|
|
}
|
|
if (endVal === startVal) {
|
|
stops[0].offset = 0;
|
|
stops[1].offset = 100;
|
|
}
|
|
else {
|
|
// normalize the offsets into percentages
|
|
if (stops[stops.length - 1].offset !== 100) {
|
|
for (const s of stops) {
|
|
s.offset = ((s.offset - startVal) / (endVal - startVal)) * 100;
|
|
}
|
|
}
|
|
}
|
|
return stops;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Based on the data, return an array with unique values.
|
|
*
|
|
* @export
|
|
* @returns array
|
|
*/
|
|
function getUniqueXDomainValues(results) {
|
|
const valueSet = new Set();
|
|
for (const result of results) {
|
|
for (const d of result.series) {
|
|
valueSet.add(d.name);
|
|
}
|
|
}
|
|
return Array.from(valueSet);
|
|
}
|
|
/**
|
|
* Get the scaleType of enumerable of values.
|
|
* @returns 'time', 'linear' or 'ordinal'
|
|
*/
|
|
function getScaleType(values, checkDateType = true) {
|
|
if (checkDateType) {
|
|
const allDates = values.every(value => value instanceof Date);
|
|
if (allDates) {
|
|
return ScaleType.Time;
|
|
}
|
|
}
|
|
const allNumbers = values.every(value => typeof value === 'number');
|
|
if (allNumbers) {
|
|
return ScaleType.Linear;
|
|
}
|
|
return ScaleType.Ordinal;
|
|
}
|
|
function getXDomainArray(values, xScaleMin, xScaleMax) {
|
|
const scaleType = getScaleType(values);
|
|
let xSet = [];
|
|
let domain = [];
|
|
if (scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
}
|
|
let min;
|
|
let max;
|
|
if (scaleType === ScaleType.Time || scaleType === ScaleType.Linear) {
|
|
const mappedValues = values.map(v => Number(v));
|
|
min = xScaleMin ? xScaleMin : Math.min(...mappedValues);
|
|
max = xScaleMax ? xScaleMax : Math.max(...mappedValues);
|
|
}
|
|
if (scaleType === ScaleType.Time) {
|
|
domain = [new Date(min), new Date(max)];
|
|
xSet = [...values].sort((a, b) => {
|
|
const aDate = a.getTime();
|
|
const bDate = b.getTime();
|
|
if (aDate > bDate)
|
|
return 1;
|
|
if (bDate > aDate)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
}
|
|
else if (scaleType === ScaleType.Linear) {
|
|
domain = [min, max];
|
|
// Use compare function to sort numbers numerically
|
|
xSet = [...values].sort((a, b) => a - b);
|
|
}
|
|
else {
|
|
domain = values;
|
|
xSet = values;
|
|
}
|
|
return { domain, xSet, scaleType };
|
|
}
|
|
|
|
function sortLinear(data, property, direction = 'asc') {
|
|
return data.sort((a, b) => {
|
|
if (direction === 'asc') {
|
|
return a[property] - b[property];
|
|
}
|
|
else {
|
|
return b[property] - a[property];
|
|
}
|
|
});
|
|
}
|
|
function sortByDomain(data, property, direction = 'asc', domain) {
|
|
return data.sort((a, b) => {
|
|
const aVal = a[property];
|
|
const bVal = b[property];
|
|
const aIdx = domain.indexOf(aVal);
|
|
const bIdx = domain.indexOf(bVal);
|
|
if (direction === 'asc') {
|
|
return aIdx - bIdx;
|
|
}
|
|
else {
|
|
return bIdx - aIdx;
|
|
}
|
|
});
|
|
}
|
|
function sortByTime(data, property, direction = 'asc') {
|
|
return data.sort((a, b) => {
|
|
const aDate = a[property].getTime();
|
|
const bDate = b[property].getTime();
|
|
if (direction === 'asc') {
|
|
if (aDate > bDate)
|
|
return 1;
|
|
if (bDate > aDate)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
else {
|
|
if (aDate > bDate)
|
|
return -1;
|
|
if (bDate > aDate)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
class AreaSeriesComponent {
|
|
constructor() {
|
|
this.baseValue = 'auto';
|
|
this.stacked = false;
|
|
this.normalized = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.updateGradient();
|
|
let currentArea;
|
|
let startingArea;
|
|
const xProperty = d => {
|
|
const label = d.name;
|
|
return this.xScale(label);
|
|
};
|
|
if (this.stacked || this.normalized) {
|
|
currentArea = area()
|
|
.x(xProperty)
|
|
.y0((d, i) => this.yScale(d.d0))
|
|
.y1((d, i) => this.yScale(d.d1));
|
|
startingArea = area()
|
|
.x(xProperty)
|
|
.y0(d => this.yScale.range()[0])
|
|
.y1(d => this.yScale.range()[0]);
|
|
}
|
|
else {
|
|
currentArea = area()
|
|
.x(xProperty)
|
|
.y0(() => (this.baseValue === 'auto' ? this.yScale.range()[0] : this.yScale(this.baseValue)))
|
|
.y1(d => this.yScale(d.value));
|
|
startingArea = area()
|
|
.x(xProperty)
|
|
.y0(d => (this.baseValue === 'auto' ? this.yScale.range()[0] : this.yScale(this.baseValue)))
|
|
.y1(d => (this.baseValue === 'auto' ? this.yScale.range()[0] : this.yScale(this.baseValue)));
|
|
}
|
|
currentArea.curve(this.curve);
|
|
startingArea.curve(this.curve);
|
|
this.opacity = 0.8;
|
|
let data = this.data.series;
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
data = sortLinear(data, 'name');
|
|
}
|
|
else if (this.scaleType === ScaleType.Time) {
|
|
data = sortByTime(data, 'name');
|
|
}
|
|
else {
|
|
data = sortByDomain(data, 'name', 'asc', this.xScale.domain());
|
|
}
|
|
this.path = currentArea(data);
|
|
this.startingPath = startingArea(data);
|
|
}
|
|
updateGradient() {
|
|
if (this.colors.scaleType === ScaleType.Linear) {
|
|
this.hasGradient = true;
|
|
if (this.stacked || this.normalized) {
|
|
const d0values = this.data.series.map(d => d.d0);
|
|
const d1values = this.data.series.map(d => d.d1);
|
|
const max = Math.max(...d1values);
|
|
const min = Math.min(...d0values);
|
|
this.gradientStops = this.colors.getLinearGradientStops(max, min);
|
|
}
|
|
else {
|
|
const values = this.data.series.map(d => d.value);
|
|
const max = Math.max(...values);
|
|
this.gradientStops = this.colors.getLinearGradientStops(max);
|
|
}
|
|
}
|
|
else {
|
|
this.hasGradient = false;
|
|
this.gradientStops = undefined;
|
|
}
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
isInactive(entry) {
|
|
if (!this.activeEntries || this.activeEntries.length === 0)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item === undefined;
|
|
}
|
|
}
|
|
AreaSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
AreaSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AreaSeriesComponent, selector: "g[ngx-charts-area-series]", inputs: { data: "data", xScale: "xScale", yScale: "yScale", baseValue: "baseValue", colors: "colors", scaleType: "scaleType", stacked: "stacked", normalized: "normalized", gradient: "gradient", curve: "curve", activeEntries: "activeEntries", animations: "animations" }, outputs: { select: "select" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-area
|
|
class="area-series"
|
|
[data]="data"
|
|
[path]="path"
|
|
[fill]="colors.getColor(data.name)"
|
|
[stops]="gradientStops"
|
|
[startingPath]="startingPath"
|
|
[opacity]="opacity"
|
|
[gradient]="gradient || hasGradient"
|
|
[animations]="animations"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
/>
|
|
`, isInline: true, components: [{ type: AreaComponent, selector: "g[ngx-charts-area]", inputs: ["data", "path", "startingPath", "fill", "opacity", "startOpacity", "endOpacity", "gradient", "stops", "animations"], outputs: ["select"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-area-series]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-area
|
|
class="area-series"
|
|
[data]="data"
|
|
[path]="path"
|
|
[fill]="colors.getColor(data.name)"
|
|
[stops]="gradientStops"
|
|
[startingPath]="startingPath"
|
|
[opacity]="opacity"
|
|
[gradient]="gradient || hasGradient"
|
|
[animations]="animations"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
/>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { data: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], baseValue: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], scaleType: [{
|
|
type: Input
|
|
}], stacked: [{
|
|
type: Input
|
|
}], normalized: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class AreaChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.xAxis = false;
|
|
this.yAxis = false;
|
|
this.baseValue = 'auto';
|
|
this.autoScale = false;
|
|
this.timeline = false;
|
|
this.showGridLines = true;
|
|
this.curve = curveLinear;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.roundDomains = false;
|
|
this.tooltipDisabled = false;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.timelineHeight = 50;
|
|
this.timelinePadding = 10;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.timeline) {
|
|
this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
|
}
|
|
this.xDomain = this.getXDomain();
|
|
if (this.filteredDomain) {
|
|
this.xDomain = this.filteredDomain;
|
|
}
|
|
this.yDomain = this.getYDomain();
|
|
this.seriesDomain = this.getSeriesDomain();
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
|
this.updateTimeline();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset}, ${this.margin[0]})`;
|
|
this.clipPathId = 'clip' + id().toString();
|
|
this.clipPath = `url(#${this.clipPathId})`;
|
|
}
|
|
updateTimeline() {
|
|
if (this.timeline) {
|
|
this.timelineWidth = this.dims.width;
|
|
this.timelineXDomain = this.getXDomain();
|
|
this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
|
this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
|
this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
|
}
|
|
}
|
|
getXDomain() {
|
|
let values = getUniqueXDomainValues(this.results);
|
|
this.scaleType = getScaleType(values);
|
|
let domain = [];
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
}
|
|
let min;
|
|
let max;
|
|
if (this.scaleType === ScaleType.Time || this.scaleType === ScaleType.Linear) {
|
|
min = this.xScaleMin ? this.xScaleMin : Math.min(...values);
|
|
max = this.xScaleMax ? this.xScaleMax : Math.max(...values);
|
|
}
|
|
if (this.scaleType === ScaleType.Time) {
|
|
domain = [new Date(min), new Date(max)];
|
|
this.xSet = [...values].sort((a, b) => {
|
|
const aDate = a.getTime();
|
|
const bDate = b.getTime();
|
|
if (aDate > bDate)
|
|
return 1;
|
|
if (bDate > aDate)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
domain = [min, max];
|
|
// Use compare function to sort numbers numerically
|
|
this.xSet = [...values].sort((a, b) => a - b);
|
|
}
|
|
else {
|
|
domain = values;
|
|
this.xSet = values;
|
|
}
|
|
return domain;
|
|
}
|
|
getYDomain() {
|
|
const domain = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (!domain.includes(d.value)) {
|
|
domain.push(d.value);
|
|
}
|
|
}
|
|
}
|
|
const values = [...domain];
|
|
if (!this.autoScale) {
|
|
values.push(0);
|
|
}
|
|
if (this.baseValue !== 'auto') {
|
|
values.push(this.baseValue);
|
|
}
|
|
const min = this.yScaleMin ? this.yScaleMin : Math.min(...values);
|
|
const max = this.yScaleMax ? this.yScaleMax : Math.max(...values);
|
|
return [min, max];
|
|
}
|
|
getSeriesDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
getXScale(domain, width) {
|
|
let scale;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
scale = scaleTime();
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
scale = scaleLinear();
|
|
}
|
|
else if (this.scaleType === ScaleType.Ordinal) {
|
|
scale = scalePoint().padding(0.1);
|
|
}
|
|
scale.range([0, width]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getYScale(domain, height) {
|
|
const scale = scaleLinear().range([height, 0]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getScaleType(values) {
|
|
let date = true;
|
|
let num = true;
|
|
for (const value of values) {
|
|
if (isDate(value)) {
|
|
date = false;
|
|
}
|
|
if (isNumber(value)) {
|
|
num = false;
|
|
}
|
|
}
|
|
if (date) {
|
|
return ScaleType.Time;
|
|
}
|
|
if (num) {
|
|
return ScaleType.Linear;
|
|
}
|
|
return ScaleType.Ordinal;
|
|
}
|
|
updateDomain(domain) {
|
|
this.filteredDomain = domain;
|
|
this.xDomain = this.filteredDomain;
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
}
|
|
updateHoveredVertical(item) {
|
|
this.hoveredVertical = item.value;
|
|
this.deactivateAll();
|
|
}
|
|
hideCircles() {
|
|
this.hoveredVertical = null;
|
|
this.deactivateAll();
|
|
}
|
|
onClick(data, series) {
|
|
if (series) {
|
|
data.series = series.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.seriesDomain;
|
|
}
|
|
else {
|
|
domain = this.yDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.seriesDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.yDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
deactivateAll() {
|
|
this.activeEntries = [...this.activeEntries];
|
|
for (const entry of this.activeEntries) {
|
|
this.deactivate.emit({ value: entry, entries: [] });
|
|
}
|
|
this.activeEntries = [];
|
|
}
|
|
}
|
|
AreaChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
AreaChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AreaChartComponent, selector: "ngx-charts-area-chart", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", baseValue: "baseValue", autoScale: "autoScale", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", timeline: "timeline", gradient: "gradient", showGridLines: "showGridLines", curve: "curve", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", roundDomains: "roundDomains", tooltipDisabled: "tooltipDisabled", xScaleMin: "xScaleMin", xScaleMax: "xScaleMax", yScaleMin: "yScaleMin", yScaleMax: "yScaleMax", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseleave": "hideCircles()" } }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }, { propertyName: "seriesTooltipTemplate", first: true, predicate: ["seriesTooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="area-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[baseValue]="baseValue"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[activeEntries]="activeEntries"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[legend]="legend"
|
|
[scaleType]="scaleType"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[baseValue]="baseValue"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: AreaSeriesComponent, selector: "g[ngx-charts-area-series]", inputs: ["data", "xScale", "yScale", "baseValue", "colors", "scaleType", "stacked", "normalized", "gradient", "curve", "activeEntries", "animations"], outputs: ["select"] }, { type: TooltipArea, selector: "g[ngx-charts-tooltip-area]", inputs: ["dims", "xSet", "xScale", "yScale", "results", "colors", "showPercentage", "tooltipDisabled", "tooltipTemplate"], outputs: ["hover"] }, { type: CircleSeriesComponent, selector: "g[ngx-charts-circle-series]", inputs: ["data", "type", "xScale", "yScale", "colors", "scaleType", "visibleValue", "activeEntries", "tooltipDisabled", "tooltipTemplate"], outputs: ["select", "activate", "deactivate"] }, { type: Timeline, selector: "g[ngx-charts-timeline]", inputs: ["view", "results", "scheme", "customColors", "legend", "autoScale", "scaleType", "height"], outputs: ["select", "onDomainChange"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-area-chart', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="area-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[baseValue]="baseValue"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[activeEntries]="activeEntries"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[legend]="legend"
|
|
[scaleType]="scaleType"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[baseValue]="baseValue"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], baseValue: [{
|
|
type: Input
|
|
}], autoScale: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], timeline: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], xScaleMin: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], yScaleMin: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], seriesTooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['seriesTooltipTemplate']
|
|
}], hideCircles: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class AreaChartNormalizedComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.showXAxisLabel = false;
|
|
this.showYAxisLabel = false;
|
|
this.showGridLines = true;
|
|
this.curve = curveLinear;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.roundDomains = false;
|
|
this.tooltipDisabled = false;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.yDomain = [0, 100];
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.seriesType = SeriesType;
|
|
this.timelineHeight = 50;
|
|
this.timelinePadding = 10;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.timeline) {
|
|
this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
|
}
|
|
this.xDomain = this.getXDomain();
|
|
if (this.filteredDomain) {
|
|
this.xDomain = this.filteredDomain;
|
|
}
|
|
this.seriesDomain = this.getSeriesDomain();
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
|
for (let i = 0; i < this.xSet.length; i++) {
|
|
const val = this.xSet[i];
|
|
let d0 = 0;
|
|
let total = 0;
|
|
for (const group of this.results) {
|
|
const d = group.series.find(item => {
|
|
let a = item.name;
|
|
let b = val;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
a = a.valueOf();
|
|
b = b.valueOf();
|
|
}
|
|
return a === b;
|
|
});
|
|
if (d) {
|
|
total += d.value;
|
|
}
|
|
}
|
|
for (const group of this.results) {
|
|
let d = group.series.find(item => {
|
|
let a = item.name;
|
|
let b = val;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
a = a.valueOf();
|
|
b = b.valueOf();
|
|
}
|
|
return a === b;
|
|
});
|
|
if (d) {
|
|
d.d0 = d0;
|
|
d.d1 = d0 + d.value;
|
|
d0 += d.value;
|
|
}
|
|
else {
|
|
d = {
|
|
name: val,
|
|
value: 0,
|
|
d0,
|
|
d1: d0
|
|
};
|
|
group.series.push(d);
|
|
}
|
|
if (total > 0) {
|
|
d.d0 = (d.d0 * 100) / total;
|
|
d.d1 = (d.d1 * 100) / total;
|
|
}
|
|
else {
|
|
d.d0 = 0;
|
|
d.d1 = 0;
|
|
}
|
|
}
|
|
}
|
|
this.updateTimeline();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
this.clipPathId = 'clip' + id().toString();
|
|
this.clipPath = `url(#${this.clipPathId})`;
|
|
}
|
|
updateTimeline() {
|
|
if (this.timeline) {
|
|
this.timelineWidth = this.dims.width;
|
|
this.timelineXDomain = this.getXDomain();
|
|
this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
|
this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
|
this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
|
}
|
|
}
|
|
getXDomain() {
|
|
let values = getUniqueXDomainValues(this.results);
|
|
this.scaleType = getScaleType(values);
|
|
let domain = [];
|
|
if (this.scaleType === ScaleType.Time) {
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
domain = [new Date(min), new Date(max)];
|
|
this.xSet = [...values].sort((a, b) => {
|
|
const aDate = a.getTime();
|
|
const bDate = b.getTime();
|
|
if (aDate > bDate)
|
|
return 1;
|
|
if (bDate > aDate)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
domain = [min, max];
|
|
// Use compare function to sort numbers numerically
|
|
this.xSet = [...values].sort((a, b) => a - b);
|
|
}
|
|
else {
|
|
domain = values;
|
|
this.xSet = values;
|
|
}
|
|
return domain;
|
|
}
|
|
getSeriesDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
getXScale(domain, width) {
|
|
let scale;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
scale = scaleTime();
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
scale = scaleLinear();
|
|
}
|
|
else if (this.scaleType === ScaleType.Ordinal) {
|
|
scale = scalePoint().padding(0.1);
|
|
}
|
|
scale.range([0, width]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getYScale(domain, height) {
|
|
const scale = scaleLinear().range([height, 0]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
updateDomain(domain) {
|
|
this.filteredDomain = domain;
|
|
this.xDomain = this.filteredDomain;
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
}
|
|
updateHoveredVertical(item) {
|
|
this.hoveredVertical = item.value;
|
|
this.deactivateAll();
|
|
}
|
|
hideCircles() {
|
|
this.hoveredVertical = null;
|
|
this.deactivateAll();
|
|
}
|
|
onClick(data, series) {
|
|
if (series) {
|
|
data.series = series.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.seriesDomain;
|
|
}
|
|
else {
|
|
domain = this.yDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.seriesDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.yDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
deactivateAll() {
|
|
this.activeEntries = [...this.activeEntries];
|
|
for (const entry of this.activeEntries) {
|
|
this.deactivate.emit({ value: entry, entries: [] });
|
|
}
|
|
this.activeEntries = [];
|
|
}
|
|
}
|
|
AreaChartNormalizedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartNormalizedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
AreaChartNormalizedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AreaChartNormalizedComponent, selector: "ngx-charts-area-chart-normalized", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", timeline: "timeline", gradient: "gradient", showGridLines: "showGridLines", curve: "curve", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", roundDomains: "roundDomains", tooltipDisabled: "tooltipDisabled", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseleave": "hideCircles()" } }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }, { propertyName: "seriesTooltipTemplate", first: true, predicate: ["seriesTooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="area-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[activeEntries]="activeEntries"
|
|
[gradient]="gradient"
|
|
[normalized]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[showPercentage]="true"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[type]="seriesType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[activeEntries]="activeEntries"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[legend]="legend"
|
|
[scaleType]="scaleType"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[normalized]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: AreaSeriesComponent, selector: "g[ngx-charts-area-series]", inputs: ["data", "xScale", "yScale", "baseValue", "colors", "scaleType", "stacked", "normalized", "gradient", "curve", "activeEntries", "animations"], outputs: ["select"] }, { type: TooltipArea, selector: "g[ngx-charts-tooltip-area]", inputs: ["dims", "xSet", "xScale", "yScale", "results", "colors", "showPercentage", "tooltipDisabled", "tooltipTemplate"], outputs: ["hover"] }, { type: CircleSeriesComponent, selector: "g[ngx-charts-circle-series]", inputs: ["data", "type", "xScale", "yScale", "colors", "scaleType", "visibleValue", "activeEntries", "tooltipDisabled", "tooltipTemplate"], outputs: ["select", "activate", "deactivate"] }, { type: Timeline, selector: "g[ngx-charts-timeline]", inputs: ["view", "results", "scheme", "customColors", "legend", "autoScale", "scaleType", "height"], outputs: ["select", "onDomainChange"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartNormalizedComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-area-chart-normalized', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="area-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[activeEntries]="activeEntries"
|
|
[gradient]="gradient"
|
|
[normalized]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[showPercentage]="true"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[type]="seriesType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[activeEntries]="activeEntries"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[legend]="legend"
|
|
[scaleType]="scaleType"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[normalized]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], timeline: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], seriesTooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['seriesTooltipTemplate']
|
|
}], hideCircles: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class AreaChartStackedComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.xAxis = false;
|
|
this.yAxis = false;
|
|
this.timeline = false;
|
|
this.showGridLines = true;
|
|
this.curve = curveLinear;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.roundDomains = false;
|
|
this.tooltipDisabled = false;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.timelineHeight = 50;
|
|
this.timelinePadding = 10;
|
|
this.seriesType = SeriesType;
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.timeline) {
|
|
this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
|
}
|
|
this.xDomain = this.getXDomain();
|
|
if (this.filteredDomain) {
|
|
this.xDomain = this.filteredDomain;
|
|
}
|
|
this.yDomain = this.getYDomain();
|
|
this.seriesDomain = this.getSeriesDomain();
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
|
for (let i = 0; i < this.xSet.length; i++) {
|
|
const val = this.xSet[i];
|
|
let d0 = 0;
|
|
for (const group of this.results) {
|
|
let d = group.series.find(item => {
|
|
let a = item.name;
|
|
let b = val;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
a = a.valueOf();
|
|
b = b.valueOf();
|
|
}
|
|
return a === b;
|
|
});
|
|
if (d) {
|
|
d.d0 = d0;
|
|
d.d1 = d0 + d.value;
|
|
d0 += d.value;
|
|
}
|
|
else {
|
|
d = {
|
|
name: val,
|
|
value: 0,
|
|
d0,
|
|
d1: d0
|
|
};
|
|
group.series.push(d);
|
|
}
|
|
}
|
|
}
|
|
this.updateTimeline();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
this.clipPathId = 'clip' + id().toString();
|
|
this.clipPath = `url(#${this.clipPathId})`;
|
|
}
|
|
updateTimeline() {
|
|
if (this.timeline) {
|
|
this.timelineWidth = this.dims.width;
|
|
this.timelineXDomain = this.getXDomain();
|
|
this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
|
this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
|
this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
|
}
|
|
}
|
|
getXDomain() {
|
|
let values = getUniqueXDomainValues(this.results);
|
|
this.scaleType = getScaleType(values);
|
|
let domain = [];
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
}
|
|
let min;
|
|
let max;
|
|
if (this.scaleType === ScaleType.Time || this.scaleType === ScaleType.Linear) {
|
|
min = this.xScaleMin ? this.xScaleMin : Math.min(...values);
|
|
max = this.xScaleMax ? this.xScaleMax : Math.max(...values);
|
|
}
|
|
if (this.scaleType === ScaleType.Time) {
|
|
domain = [new Date(min), new Date(max)];
|
|
this.xSet = [...values].sort((a, b) => {
|
|
const aDate = a.getTime();
|
|
const bDate = b.getTime();
|
|
if (aDate > bDate)
|
|
return 1;
|
|
if (bDate > aDate)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
domain = [min, max];
|
|
// Use compare function to sort numbers numerically
|
|
this.xSet = [...values].sort((a, b) => a - b);
|
|
}
|
|
else {
|
|
domain = values;
|
|
this.xSet = values;
|
|
}
|
|
return domain;
|
|
}
|
|
getYDomain() {
|
|
const domain = [];
|
|
for (let i = 0; i < this.xSet.length; i++) {
|
|
const val = this.xSet[i];
|
|
let sum = 0;
|
|
for (const group of this.results) {
|
|
const d = group.series.find(item => {
|
|
let a = item.name;
|
|
let b = val;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
a = a.valueOf();
|
|
b = b.valueOf();
|
|
}
|
|
return a === b;
|
|
});
|
|
if (d) {
|
|
sum += d.value;
|
|
}
|
|
}
|
|
domain.push(sum);
|
|
}
|
|
const min = this.yScaleMin ? this.yScaleMin : Math.min(0, ...domain);
|
|
const max = this.yScaleMax ? this.yScaleMax : Math.max(...domain);
|
|
return [min, max];
|
|
}
|
|
getSeriesDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
getXScale(domain, width) {
|
|
let scale;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
scale = scaleTime();
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
scale = scaleLinear();
|
|
}
|
|
else if (this.scaleType === ScaleType.Ordinal) {
|
|
scale = scalePoint().padding(0.1);
|
|
}
|
|
scale.range([0, width]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getYScale(domain, height) {
|
|
const scale = scaleLinear().range([height, 0]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
updateDomain(domain) {
|
|
this.filteredDomain = domain;
|
|
this.xDomain = this.filteredDomain;
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
}
|
|
updateHoveredVertical(item) {
|
|
this.hoveredVertical = item.value;
|
|
this.deactivateAll();
|
|
}
|
|
hideCircles() {
|
|
this.hoveredVertical = null;
|
|
this.deactivateAll();
|
|
}
|
|
onClick(data, series) {
|
|
if (series) {
|
|
data.series = series.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
trackBy(index, item) {
|
|
return `${item.name}`;
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.seriesDomain;
|
|
}
|
|
else {
|
|
domain = this.yDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.seriesDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.yDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
deactivateAll() {
|
|
this.activeEntries = [...this.activeEntries];
|
|
for (const entry of this.activeEntries) {
|
|
this.deactivate.emit({ value: entry, entries: [] });
|
|
}
|
|
this.activeEntries = [];
|
|
}
|
|
}
|
|
AreaChartStackedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
AreaChartStackedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AreaChartStackedComponent, selector: "ngx-charts-area-chart-stacked", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", timeline: "timeline", gradient: "gradient", showGridLines: "showGridLines", curve: "curve", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", roundDomains: "roundDomains", tooltipDisabled: "tooltipDisabled", xScaleMin: "xScaleMin", xScaleMax: "xScaleMax", yScaleMin: "yScaleMin", yScaleMax: "yScaleMax", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseleave": "hideCircles()" } }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }, { propertyName: "seriesTooltipTemplate", first: true, predicate: ["seriesTooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="area-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[activeEntries]="activeEntries"
|
|
[stacked]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[type]="seriesType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[activeEntries]="activeEntries"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[legend]="legend"
|
|
[scaleType]="scaleType"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[stacked]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: AreaSeriesComponent, selector: "g[ngx-charts-area-series]", inputs: ["data", "xScale", "yScale", "baseValue", "colors", "scaleType", "stacked", "normalized", "gradient", "curve", "activeEntries", "animations"], outputs: ["select"] }, { type: TooltipArea, selector: "g[ngx-charts-tooltip-area]", inputs: ["dims", "xSet", "xScale", "yScale", "results", "colors", "showPercentage", "tooltipDisabled", "tooltipTemplate"], outputs: ["hover"] }, { type: CircleSeriesComponent, selector: "g[ngx-charts-circle-series]", inputs: ["data", "type", "xScale", "yScale", "colors", "scaleType", "visibleValue", "activeEntries", "tooltipDisabled", "tooltipTemplate"], outputs: ["select", "activate", "deactivate"] }, { type: Timeline, selector: "g[ngx-charts-timeline]", inputs: ["view", "results", "scheme", "customColors", "legend", "autoScale", "scaleType", "height"], outputs: ["select", "onDomainChange"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartStackedComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-area-chart-stacked', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="area-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[activeEntries]="activeEntries"
|
|
[stacked]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[type]="seriesType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[activeEntries]="activeEntries"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[legend]="legend"
|
|
[scaleType]="scaleType"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-area-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[gradient]="gradient"
|
|
[stacked]="true"
|
|
[curve]="curve"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], timeline: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], xScaleMin: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], yScaleMin: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], seriesTooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['seriesTooltipTemplate']
|
|
}], hideCircles: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class AreaChartModule {
|
|
}
|
|
AreaChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
AreaChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartModule, declarations: [AreaChartComponent, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaSeriesComponent], imports: [ChartCommonModule], exports: [AreaChartComponent, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaSeriesComponent] });
|
|
AreaChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AreaChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [AreaChartComponent, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaSeriesComponent],
|
|
exports: [AreaChartComponent, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaSeriesComponent]
|
|
}]
|
|
}] });
|
|
|
|
class BarComponent {
|
|
constructor(element) {
|
|
this.roundEdges = true;
|
|
this.gradient = false;
|
|
this.offset = 0;
|
|
this.isActive = false;
|
|
this.animations = true;
|
|
this.noBarWhenZero = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.hasGradient = false;
|
|
this.hideBar = false;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
if (changes.roundEdges) {
|
|
this.loadAnimation();
|
|
}
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientFill = `url(#${this.gradientId})`;
|
|
if (this.gradient || this.stops) {
|
|
this.gradientStops = this.getGradient();
|
|
this.hasGradient = true;
|
|
}
|
|
else {
|
|
this.hasGradient = false;
|
|
}
|
|
this.updatePathEl();
|
|
this.checkToHideBar();
|
|
}
|
|
loadAnimation() {
|
|
this.path = this.getStartingPath();
|
|
setTimeout(this.update.bind(this), 100);
|
|
}
|
|
updatePathEl() {
|
|
const node = select(this.element).select('.bar');
|
|
const path = this.getPath();
|
|
if (this.animations) {
|
|
node.transition().duration(500).attr('d', path);
|
|
}
|
|
else {
|
|
node.attr('d', path);
|
|
}
|
|
}
|
|
getGradient() {
|
|
if (this.stops) {
|
|
return this.stops;
|
|
}
|
|
return [
|
|
{
|
|
offset: 0,
|
|
color: this.fill,
|
|
opacity: this.getStartOpacity()
|
|
},
|
|
{
|
|
offset: 100,
|
|
color: this.fill,
|
|
opacity: 1
|
|
}
|
|
];
|
|
}
|
|
getStartingPath() {
|
|
if (!this.animations) {
|
|
return this.getPath();
|
|
}
|
|
let radius = this.getRadius();
|
|
let path;
|
|
if (this.roundEdges) {
|
|
if (this.orientation === BarOrientation.Vertical) {
|
|
radius = Math.min(this.height, radius);
|
|
path = roundedRect(this.x, this.y + this.height, this.width, 1, 0, this.edges);
|
|
}
|
|
else if (this.orientation === BarOrientation.Horizontal) {
|
|
radius = Math.min(this.width, radius);
|
|
path = roundedRect(this.x, this.y, 1, this.height, 0, this.edges);
|
|
}
|
|
}
|
|
else {
|
|
if (this.orientation === BarOrientation.Vertical) {
|
|
path = roundedRect(this.x, this.y + this.height, this.width, 1, 0, this.edges);
|
|
}
|
|
else if (this.orientation === BarOrientation.Horizontal) {
|
|
path = roundedRect(this.x, this.y, 1, this.height, 0, this.edges);
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
getPath() {
|
|
let radius = this.getRadius();
|
|
let path;
|
|
if (this.roundEdges) {
|
|
if (this.orientation === BarOrientation.Vertical) {
|
|
radius = Math.min(this.height, radius);
|
|
path = roundedRect(this.x, this.y, this.width, this.height, radius, this.edges);
|
|
}
|
|
else if (this.orientation === BarOrientation.Horizontal) {
|
|
radius = Math.min(this.width, radius);
|
|
path = roundedRect(this.x, this.y, this.width, this.height, radius, this.edges);
|
|
}
|
|
}
|
|
else {
|
|
path = roundedRect(this.x, this.y, this.width, this.height, radius, this.edges);
|
|
}
|
|
return path;
|
|
}
|
|
getRadius() {
|
|
let radius = 0;
|
|
if (this.roundEdges && this.height > 5 && this.width > 5) {
|
|
radius = Math.floor(Math.min(5, this.height / 2, this.width / 2));
|
|
}
|
|
return radius;
|
|
}
|
|
getStartOpacity() {
|
|
if (this.roundEdges) {
|
|
return 0.2;
|
|
}
|
|
else {
|
|
return 0.5;
|
|
}
|
|
}
|
|
get edges() {
|
|
let edges = [false, false, false, false];
|
|
if (this.roundEdges) {
|
|
if (this.orientation === BarOrientation.Vertical) {
|
|
if (this.data.value > 0) {
|
|
edges = [true, true, false, false];
|
|
}
|
|
else {
|
|
edges = [false, false, true, true];
|
|
}
|
|
}
|
|
else if (this.orientation === BarOrientation.Horizontal) {
|
|
if (this.data.value > 0) {
|
|
edges = [false, true, false, true];
|
|
}
|
|
else {
|
|
edges = [true, false, true, false];
|
|
}
|
|
}
|
|
}
|
|
return edges;
|
|
}
|
|
onMouseEnter() {
|
|
this.activate.emit(this.data);
|
|
}
|
|
onMouseLeave() {
|
|
this.deactivate.emit(this.data);
|
|
}
|
|
checkToHideBar() {
|
|
this.hideBar =
|
|
this.noBarWhenZero &&
|
|
((this.orientation === BarOrientation.Vertical && this.height === 0) ||
|
|
(this.orientation === BarOrientation.Horizontal && this.width === 0));
|
|
}
|
|
}
|
|
BarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
BarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarComponent, selector: "g[ngx-charts-bar]", inputs: { fill: "fill", data: "data", width: "width", height: "height", x: "x", y: "y", orientation: "orientation", roundEdges: "roundEdges", gradient: "gradient", offset: "offset", isActive: "isActive", stops: "stops", animations: "animations", ariaLabel: "ariaLabel", noBarWhenZero: "noBarWhenZero" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:defs *ngIf="hasGradient">
|
|
<svg:g ngx-charts-svg-linear-gradient [orientation]="orientation" [name]="gradientId" [stops]="gradientStops" />
|
|
</svg:defs>
|
|
<svg:path
|
|
class="bar"
|
|
stroke="none"
|
|
role="img"
|
|
tabIndex="-1"
|
|
[class.active]="isActive"
|
|
[class.hidden]="hideBar"
|
|
[attr.d]="path"
|
|
[attr.aria-label]="ariaLabel"
|
|
[attr.fill]="hasGradient ? gradientFill : fill"
|
|
(click)="select.emit(data)"
|
|
/>
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-bar]',
|
|
template: `
|
|
<svg:defs *ngIf="hasGradient">
|
|
<svg:g ngx-charts-svg-linear-gradient [orientation]="orientation" [name]="gradientId" [stops]="gradientStops" />
|
|
</svg:defs>
|
|
<svg:path
|
|
class="bar"
|
|
stroke="none"
|
|
role="img"
|
|
tabIndex="-1"
|
|
[class.active]="isActive"
|
|
[class.hidden]="hideBar"
|
|
[attr.d]="path"
|
|
[attr.aria-label]="ariaLabel"
|
|
[attr.fill]="hasGradient ? gradientFill : fill"
|
|
(click)="select.emit(data)"
|
|
/>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { fill: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], x: [{
|
|
type: Input
|
|
}], y: [{
|
|
type: Input
|
|
}], orientation: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], offset: [{
|
|
type: Input
|
|
}], isActive: [{
|
|
type: Input
|
|
}], stops: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], ariaLabel: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], onMouseEnter: [{
|
|
type: HostListener,
|
|
args: ['mouseenter']
|
|
}], onMouseLeave: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
var BarChartType;
|
|
(function (BarChartType) {
|
|
BarChartType["Standard"] = "standard";
|
|
BarChartType["Normalized"] = "normalized";
|
|
BarChartType["Stacked"] = "stacked";
|
|
})(BarChartType || (BarChartType = {}));
|
|
|
|
var D0Types;
|
|
(function (D0Types) {
|
|
D0Types["positive"] = "positive";
|
|
D0Types["negative"] = "negative";
|
|
})(D0Types || (D0Types = {}));
|
|
|
|
class BarLabelComponent {
|
|
constructor(element) {
|
|
this.dimensionsChanged = new EventEmitter();
|
|
this.horizontalPadding = 2;
|
|
this.verticalPadding = 5;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
getSize() {
|
|
const h = this.element.getBoundingClientRect().height;
|
|
const w = this.element.getBoundingClientRect().width;
|
|
return { height: h, width: w, negative: this.value < 0 };
|
|
}
|
|
ngAfterViewInit() {
|
|
this.dimensionsChanged.emit(this.getSize());
|
|
}
|
|
update() {
|
|
if (this.valueFormatting) {
|
|
this.formatedValue = this.valueFormatting(this.value);
|
|
}
|
|
else {
|
|
this.formatedValue = formatLabel(this.value);
|
|
}
|
|
if (this.orientation === 'horizontal') {
|
|
this.x = this.barX + this.barWidth;
|
|
// if the value is negative then it's on the left of the x0.
|
|
// we need to put the data label in front of the bar
|
|
if (this.value < 0) {
|
|
this.x = this.x - this.horizontalPadding;
|
|
this.textAnchor = 'end';
|
|
}
|
|
else {
|
|
this.x = this.x + this.horizontalPadding;
|
|
this.textAnchor = 'start';
|
|
}
|
|
this.y = this.barY + this.barHeight / 2;
|
|
}
|
|
else {
|
|
// orientation must be "vertical"
|
|
this.x = this.barX + this.barWidth / 2;
|
|
this.y = this.barY + this.barHeight;
|
|
if (this.value < 0) {
|
|
this.y = this.y + this.verticalPadding;
|
|
this.textAnchor = 'end';
|
|
}
|
|
else {
|
|
this.y = this.y - this.verticalPadding;
|
|
this.textAnchor = 'start';
|
|
}
|
|
this.transform = `rotate(-45, ${this.x} , ${this.y})`;
|
|
}
|
|
}
|
|
}
|
|
BarLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarLabelComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
BarLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarLabelComponent, selector: "g[ngx-charts-bar-label]", inputs: { value: "value", valueFormatting: "valueFormatting", barX: "barX", barY: "barY", barWidth: "barWidth", barHeight: "barHeight", orientation: "orientation" }, outputs: { dimensionsChanged: "dimensionsChanged" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:text
|
|
class="textDataLabel"
|
|
alignment-baseline="middle"
|
|
[attr.text-anchor]="textAnchor"
|
|
[attr.transform]="transform"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
>
|
|
{{ formatedValue }}
|
|
</svg:text>
|
|
`, isInline: true, styles: [".textDataLabel{font-size:11px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarLabelComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'g[ngx-charts-bar-label]', template: `
|
|
<svg:text
|
|
class="textDataLabel"
|
|
alignment-baseline="middle"
|
|
[attr.text-anchor]="textAnchor"
|
|
[attr.transform]="transform"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
>
|
|
{{ formatedValue }}
|
|
</svg:text>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".textDataLabel{font-size:11px}\n"] }]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { value: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], barX: [{
|
|
type: Input
|
|
}], barY: [{
|
|
type: Input
|
|
}], barWidth: [{
|
|
type: Input
|
|
}], barHeight: [{
|
|
type: Input
|
|
}], orientation: [{
|
|
type: Input
|
|
}], dimensionsChanged: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class SeriesHorizontal {
|
|
constructor() {
|
|
this.type = BarChartType.Standard;
|
|
this.tooltipDisabled = false;
|
|
this.animations = true;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.dataLabelWidthChanged = new EventEmitter();
|
|
this.barsForDataLabels = [];
|
|
this.barOrientation = BarOrientation;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.updateTooltipSettings();
|
|
const d0 = {
|
|
[D0Types.positive]: 0,
|
|
[D0Types.negative]: 0
|
|
};
|
|
let d0Type;
|
|
d0Type = D0Types.positive;
|
|
let total;
|
|
if (this.type === BarChartType.Normalized) {
|
|
total = this.series.map(d => d.value).reduce((sum, d) => sum + d, 0);
|
|
}
|
|
const xScaleMin = Math.max(this.xScale.domain()[0], 0);
|
|
this.bars = this.series.map(d => {
|
|
let value = d.value;
|
|
const label = this.getLabel(d);
|
|
const formattedLabel = formatLabel(label);
|
|
const roundEdges = this.roundEdges;
|
|
d0Type = value > 0 ? D0Types.positive : D0Types.negative;
|
|
const bar = {
|
|
value,
|
|
label,
|
|
roundEdges,
|
|
data: d,
|
|
formattedLabel
|
|
};
|
|
bar.height = this.yScale.bandwidth();
|
|
if (this.type === BarChartType.Standard) {
|
|
bar.width = Math.abs(this.xScale(value) - this.xScale(xScaleMin));
|
|
if (value < 0) {
|
|
bar.x = this.xScale(value);
|
|
}
|
|
else {
|
|
bar.x = this.xScale(xScaleMin);
|
|
}
|
|
bar.y = this.yScale(label);
|
|
}
|
|
else if (this.type === BarChartType.Stacked) {
|
|
const offset0 = d0[d0Type];
|
|
const offset1 = offset0 + value;
|
|
d0[d0Type] += value;
|
|
bar.width = this.xScale(offset1) - this.xScale(offset0);
|
|
bar.x = this.xScale(offset0);
|
|
bar.y = 0;
|
|
bar.offset0 = offset0;
|
|
bar.offset1 = offset1;
|
|
}
|
|
else if (this.type === BarChartType.Normalized) {
|
|
let offset0 = d0[d0Type];
|
|
let offset1 = offset0 + value;
|
|
d0[d0Type] += value;
|
|
if (total > 0) {
|
|
offset0 = (offset0 * 100) / total;
|
|
offset1 = (offset1 * 100) / total;
|
|
}
|
|
else {
|
|
offset0 = 0;
|
|
offset1 = 0;
|
|
}
|
|
bar.width = this.xScale(offset1) - this.xScale(offset0);
|
|
bar.x = this.xScale(offset0);
|
|
bar.y = 0;
|
|
bar.offset0 = offset0;
|
|
bar.offset1 = offset1;
|
|
value = (offset1 - offset0).toFixed(2) + '%';
|
|
}
|
|
if (this.colors.scaleType === ScaleType.Ordinal) {
|
|
bar.color = this.colors.getColor(label);
|
|
}
|
|
else {
|
|
if (this.type === BarChartType.Standard) {
|
|
bar.color = this.colors.getColor(value);
|
|
bar.gradientStops = this.colors.getLinearGradientStops(value);
|
|
}
|
|
else {
|
|
bar.color = this.colors.getColor(bar.offset1);
|
|
bar.gradientStops = this.colors.getLinearGradientStops(bar.offset1, bar.offset0);
|
|
}
|
|
}
|
|
let tooltipLabel = formattedLabel;
|
|
bar.ariaLabel = formattedLabel + ' ' + value.toLocaleString();
|
|
if (this.seriesName !== null && this.seriesName !== undefined) {
|
|
tooltipLabel = `${this.seriesName} • ${formattedLabel}`;
|
|
bar.data.series = this.seriesName;
|
|
bar.ariaLabel = this.seriesName + ' ' + bar.ariaLabel;
|
|
}
|
|
bar.tooltipText = this.tooltipDisabled
|
|
? undefined
|
|
: `
|
|
<span class="tooltip-label">${escapeLabel(tooltipLabel)}</span>
|
|
<span class="tooltip-val">${this.dataLabelFormatting ? this.dataLabelFormatting(value) : value.toLocaleString()}</span>
|
|
`;
|
|
return bar;
|
|
});
|
|
this.updateDataLabels();
|
|
}
|
|
updateDataLabels() {
|
|
if (this.type === BarChartType.Stacked) {
|
|
this.barsForDataLabels = [];
|
|
const section = {};
|
|
section.series = this.seriesName;
|
|
const totalPositive = this.series.map(d => d.value).reduce((sum, d) => (d > 0 ? sum + d : sum), 0);
|
|
const totalNegative = this.series.map(d => d.value).reduce((sum, d) => (d < 0 ? sum + d : sum), 0);
|
|
section.total = totalPositive + totalNegative;
|
|
section.x = 0;
|
|
section.y = 0;
|
|
// if total is positive then we show it on the right, otherwise on the left
|
|
if (section.total > 0) {
|
|
section.width = this.xScale(totalPositive);
|
|
}
|
|
else {
|
|
section.width = this.xScale(totalNegative);
|
|
}
|
|
section.height = this.yScale.bandwidth();
|
|
this.barsForDataLabels.push(section);
|
|
}
|
|
else {
|
|
this.barsForDataLabels = this.series.map(d => {
|
|
const section = {};
|
|
section.series = this.seriesName ?? d.label;
|
|
section.total = d.value;
|
|
section.x = this.xScale(0);
|
|
section.y = this.yScale(d.label);
|
|
section.width = this.xScale(section.total) - this.xScale(0);
|
|
section.height = this.yScale.bandwidth();
|
|
return section;
|
|
});
|
|
}
|
|
}
|
|
updateTooltipSettings() {
|
|
this.tooltipPlacement = this.tooltipDisabled ? undefined : PlacementTypes.Top;
|
|
this.tooltipType = this.tooltipDisabled ? undefined : StyleTypes.tooltip;
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(active => {
|
|
return entry.name === active.name && entry.value === active.value;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
getLabel(dataItem) {
|
|
if (dataItem.label) {
|
|
return dataItem.label;
|
|
}
|
|
return dataItem.name;
|
|
}
|
|
trackBy(index, bar) {
|
|
return bar.label;
|
|
}
|
|
trackDataLabelBy(index, barLabel) {
|
|
return index + '#' + barLabel.series + '#' + barLabel.total;
|
|
}
|
|
click(data) {
|
|
this.select.emit(data);
|
|
}
|
|
}
|
|
SeriesHorizontal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SeriesHorizontal, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
SeriesHorizontal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: SeriesHorizontal, selector: "g[ngx-charts-series-horizontal]", inputs: { dims: "dims", type: "type", series: "series", xScale: "xScale", yScale: "yScale", colors: "colors", tooltipDisabled: "tooltipDisabled", gradient: "gradient", activeEntries: "activeEntries", seriesName: "seriesName", tooltipTemplate: "tooltipTemplate", roundEdges: "roundEdges", animations: "animations", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate", dataLabelWidthChanged: "dataLabelWidthChanged" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-bar
|
|
*ngFor="let bar of bars; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[width]="bar.width"
|
|
[height]="bar.height"
|
|
[x]="bar.x"
|
|
[y]="bar.y"
|
|
[fill]="bar.color"
|
|
[stops]="bar.gradientStops"
|
|
[data]="bar.data"
|
|
[orientation]="barOrientation.Horizontal"
|
|
[roundEdges]="bar.roundEdges"
|
|
(select)="click($event)"
|
|
[gradient]="gradient"
|
|
[isActive]="isActive(bar.data)"
|
|
[ariaLabel]="bar.ariaLabel"
|
|
[animations]="animations"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="bar.data"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
></svg:g>
|
|
<svg:g *ngIf="showDataLabel">
|
|
<svg:g
|
|
ngx-charts-bar-label
|
|
*ngFor="let b of barsForDataLabels; let i = index; trackBy: trackDataLabelBy"
|
|
[barX]="b.x"
|
|
[barY]="b.y"
|
|
[barWidth]="b.width"
|
|
[barHeight]="b.height"
|
|
[value]="b.total"
|
|
[valueFormatting]="dataLabelFormatting"
|
|
[orientation]="barOrientation.Horizontal"
|
|
(dimensionsChanged)="dataLabelWidthChanged.emit({ size: $event, index: i })"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: BarComponent, selector: "g[ngx-charts-bar]", inputs: ["fill", "data", "width", "height", "x", "y", "orientation", "roundEdges", "gradient", "offset", "isActive", "stops", "animations", "ariaLabel", "noBarWhenZero"], outputs: ["select", "activate", "deactivate"] }, { type: BarLabelComponent, selector: "g[ngx-charts-bar-label]", inputs: ["value", "valueFormatting", "barX", "barY", "barWidth", "barHeight", "orientation"], outputs: ["dimensionsChanged"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SeriesHorizontal, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-series-horizontal]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-bar
|
|
*ngFor="let bar of bars; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[width]="bar.width"
|
|
[height]="bar.height"
|
|
[x]="bar.x"
|
|
[y]="bar.y"
|
|
[fill]="bar.color"
|
|
[stops]="bar.gradientStops"
|
|
[data]="bar.data"
|
|
[orientation]="barOrientation.Horizontal"
|
|
[roundEdges]="bar.roundEdges"
|
|
(select)="click($event)"
|
|
[gradient]="gradient"
|
|
[isActive]="isActive(bar.data)"
|
|
[ariaLabel]="bar.ariaLabel"
|
|
[animations]="animations"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="bar.data"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
></svg:g>
|
|
<svg:g *ngIf="showDataLabel">
|
|
<svg:g
|
|
ngx-charts-bar-label
|
|
*ngFor="let b of barsForDataLabels; let i = index; trackBy: trackDataLabelBy"
|
|
[barX]="b.x"
|
|
[barY]="b.y"
|
|
[barWidth]="b.width"
|
|
[barHeight]="b.height"
|
|
[value]="b.total"
|
|
[valueFormatting]="dataLabelFormatting"
|
|
[orientation]="barOrientation.Horizontal"
|
|
(dimensionsChanged)="dataLabelWidthChanged.emit({ size: $event, index: i })"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], propDecorators: { dims: [{
|
|
type: Input
|
|
}], type: [{
|
|
type: Input
|
|
}], series: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], seriesName: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], dataLabelWidthChanged: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class BarHorizontalComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.roundEdges = true;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showDataLabel) {
|
|
this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
|
}
|
|
this.margin = [10, 20 + this.dataLabelMaxWidth.positive, 10, 20 + this.dataLabelMaxWidth.negative];
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getXScale() {
|
|
this.xDomain = this.getXDomain();
|
|
const scale = scaleLinear().range([0, this.dims.width]).domain(this.xDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getYScale() {
|
|
this.yDomain = this.getYDomain();
|
|
const spacing = this.yDomain.length / (this.dims.height / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, this.dims.height]).paddingInner(spacing).domain(this.yDomain);
|
|
}
|
|
getXDomain() {
|
|
const values = this.results.map(d => d.value);
|
|
const min = this.xScaleMin ? Math.min(this.xScaleMin, ...values) : Math.min(0, ...values);
|
|
const max = this.xScaleMax ? Math.max(this.xScaleMax, ...values) : Math.max(0, ...values);
|
|
return [min, max];
|
|
}
|
|
getYDomain() {
|
|
return this.results.map(d => d.label);
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.yDomain;
|
|
}
|
|
else {
|
|
domain = this.xDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === 'ordinal') {
|
|
opts.domain = this.yDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.xDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onDataLabelMaxWidthChanged(event) {
|
|
if (event.size.negative) {
|
|
this.dataLabelMaxWidth.negative = Math.max(this.dataLabelMaxWidth.negative, event.size.width);
|
|
}
|
|
else {
|
|
this.dataLabelMaxWidth.positive = Math.max(this.dataLabelMaxWidth.positive, event.size.width);
|
|
}
|
|
if (event.index === this.results.length - 1) {
|
|
setTimeout(() => this.update());
|
|
}
|
|
}
|
|
onActivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarHorizontalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontalComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarHorizontalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarHorizontalComponent, selector: "ngx-charts-bar-horizontal", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", barPadding: "barPadding", roundDomains: "roundDomains", roundEdges: "roundEdges", xScaleMax: "xScaleMax", xScaleMin: "xScaleMin", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, true)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[yAxisOffset]="dataLabelMaxWidth.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="results"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[activeEntries]="activeEntries"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesHorizontal, selector: "g[ngx-charts-series-horizontal]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "tooltipDisabled", "gradient", "activeEntries", "seriesName", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelWidthChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontalComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-horizontal', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, true)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[yAxisOffset]="dataLabelMaxWidth.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="results"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[activeEntries]="activeEntries"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], xScaleMin: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarHorizontal2DComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.groupPadding = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.roundEdges = true;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
|
this.isSSR = false;
|
|
this.barOrientation = BarOrientation;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showDataLabel) {
|
|
this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
|
}
|
|
this.margin = [10, 20 + this.dataLabelMaxWidth.positive, 10, 20 + this.dataLabelMaxWidth.negative];
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
this.groupDomain = this.getGroupDomain();
|
|
this.innerDomain = this.getInnerDomain();
|
|
this.valueDomain = this.getValueDomain();
|
|
this.groupScale = this.getGroupScale();
|
|
this.innerScale = this.getInnerScale();
|
|
this.valueScale = this.getValueScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getGroupScale() {
|
|
const spacing = this.groupDomain.length / (this.dims.height / this.groupPadding + 1);
|
|
return scaleBand()
|
|
.rangeRound([0, this.dims.height])
|
|
.paddingInner(spacing)
|
|
.paddingOuter(spacing / 2)
|
|
.domain(this.groupDomain);
|
|
}
|
|
getInnerScale() {
|
|
const height = this.groupScale.bandwidth();
|
|
const spacing = this.innerDomain.length / (height / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, height]).paddingInner(spacing).domain(this.innerDomain);
|
|
}
|
|
getValueScale() {
|
|
const scale = scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getGroupDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.label)) {
|
|
domain.push(group.label);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getInnerDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.label)) {
|
|
domain.push(d.label);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getValueDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.value)) {
|
|
domain.push(d.value);
|
|
}
|
|
}
|
|
}
|
|
const min = Math.min(0, ...domain);
|
|
const max = this.xScaleMax ? Math.max(this.xScaleMax, ...domain) : Math.max(0, ...domain);
|
|
return [min, max];
|
|
}
|
|
groupTransform(group) {
|
|
return `translate(0, ${this.groupScale(group.label)})`;
|
|
}
|
|
onClick(data, group) {
|
|
if (group) {
|
|
data.series = group.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.innerDomain;
|
|
}
|
|
else {
|
|
domain = this.valueDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.innerDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.valueDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onDataLabelMaxWidthChanged(event, groupIndex) {
|
|
if (event.size.negative) {
|
|
this.dataLabelMaxWidth.negative = Math.max(this.dataLabelMaxWidth.negative, event.size.width);
|
|
}
|
|
else {
|
|
this.dataLabelMaxWidth.positive = Math.max(this.dataLabelMaxWidth.positive, event.size.width);
|
|
}
|
|
if (groupIndex === this.results.length - 1) {
|
|
setTimeout(() => this.update());
|
|
}
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarHorizontal2DComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontal2DComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarHorizontal2DComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarHorizontal2DComponent, selector: "ngx-charts-bar-horizontal-2d", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", groupPadding: "groupPadding", barPadding: "barPadding", roundDomains: "roundDomains", roundEdges: "roundEdges", xScaleMax: "xScaleMax", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-grid-panel-series
|
|
[xScale]="valueScale"
|
|
[yScale]="groupScale"
|
|
[data]="results"
|
|
[dims]="dims"
|
|
[orient]="barOrientation.Horizontal"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="valueScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="groupScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[yAxisOffset]="dataLabelMaxWidth.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[xScale]="valueScale"
|
|
[activeEntries]="activeEntries"
|
|
[yScale]="innerScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[xScale]="valueScale"
|
|
[activeEntries]="activeEntries"
|
|
[yScale]="innerScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: GridPanelSeriesComponent, selector: "g[ngx-charts-grid-panel-series]", inputs: ["data", "dims", "xScale", "yScale", "orient"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesHorizontal, selector: "g[ngx-charts-series-horizontal]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "tooltipDisabled", "gradient", "activeEntries", "seriesName", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelWidthChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontal2DComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-horizontal-2d', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-grid-panel-series
|
|
[xScale]="valueScale"
|
|
[yScale]="groupScale"
|
|
[data]="results"
|
|
[dims]="dims"
|
|
[orient]="barOrientation.Horizontal"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="valueScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="groupScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[yAxisOffset]="dataLabelMaxWidth.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[xScale]="valueScale"
|
|
[activeEntries]="activeEntries"
|
|
[yScale]="innerScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[xScale]="valueScale"
|
|
[activeEntries]="activeEntries"
|
|
[yScale]="innerScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], groupPadding: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarHorizontalNormalizedComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.valueDomain = [0, 100];
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.barChartType = BarChartType;
|
|
this.isSSR = false;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
this.groupDomain = this.getGroupDomain();
|
|
this.innerDomain = this.getInnerDomain();
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getGroupDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.label)) {
|
|
domain.push(group.label);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getInnerDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.label)) {
|
|
domain.push(d.label);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getYScale() {
|
|
const spacing = this.groupDomain.length / (this.dims.height / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, this.dims.height]).paddingInner(spacing).domain(this.groupDomain);
|
|
}
|
|
getXScale() {
|
|
const scale = scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
groupTransform(group) {
|
|
return `translate(0, ${this.yScale(group.name)})`;
|
|
}
|
|
onClick(data, group) {
|
|
if (group) {
|
|
data.series = group.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.innerDomain;
|
|
}
|
|
else {
|
|
domain = this.valueDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.innerDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.valueDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarHorizontalNormalizedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontalNormalizedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarHorizontalNormalizedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarHorizontalNormalizedComponent, selector: "ngx-charts-bar-horizontal-normalized", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", barPadding: "barPadding", roundDomains: "roundDomains", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g *ngFor="let group of results; trackBy: trackBy" [attr.transform]="groupTransform(group)">
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesHorizontal, selector: "g[ngx-charts-series-horizontal]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "tooltipDisabled", "gradient", "activeEntries", "seriesName", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelWidthChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontalNormalizedComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-horizontal-normalized', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g *ngFor="let group of results; trackBy: trackBy" [attr.transform]="groupTransform(group)">
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarHorizontalStackedComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
|
this.barChartType = BarChartType;
|
|
this.isSSR = false;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showDataLabel) {
|
|
this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
|
}
|
|
this.margin = [10, 20 + this.dataLabelMaxWidth.positive, 10, 20 + this.dataLabelMaxWidth.negative];
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
this.groupDomain = this.getGroupDomain();
|
|
this.innerDomain = this.getInnerDomain();
|
|
this.valueDomain = this.getValueDomain();
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getGroupDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.label)) {
|
|
domain.push(group.label);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getInnerDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.label)) {
|
|
domain.push(d.label);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getValueDomain() {
|
|
const domain = [];
|
|
let smallest = 0;
|
|
let biggest = 0;
|
|
for (const group of this.results) {
|
|
let smallestSum = 0;
|
|
let biggestSum = 0;
|
|
for (const d of group.series) {
|
|
if (d.value < 0) {
|
|
smallestSum += d.value;
|
|
}
|
|
else {
|
|
biggestSum += d.value;
|
|
}
|
|
smallest = d.value < smallest ? d.value : smallest;
|
|
biggest = d.value > biggest ? d.value : biggest;
|
|
}
|
|
domain.push(smallestSum);
|
|
domain.push(biggestSum);
|
|
}
|
|
domain.push(smallest);
|
|
domain.push(biggest);
|
|
const min = Math.min(0, ...domain);
|
|
const max = this.xScaleMax ? Math.max(this.xScaleMax, ...domain) : Math.max(...domain);
|
|
return [min, max];
|
|
}
|
|
getYScale() {
|
|
const spacing = this.groupDomain.length / (this.dims.height / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, this.dims.height]).paddingInner(spacing).domain(this.groupDomain);
|
|
}
|
|
getXScale() {
|
|
const scale = scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
groupTransform(group) {
|
|
return `translate(0, ${this.yScale(group.name)})`;
|
|
}
|
|
onClick(data, group) {
|
|
if (group) {
|
|
data.series = group.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.innerDomain;
|
|
}
|
|
else {
|
|
domain = this.valueDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.innerDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.valueDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onDataLabelMaxWidthChanged(event, groupIndex) {
|
|
if (event.size.negative) {
|
|
this.dataLabelMaxWidth.negative = Math.max(this.dataLabelMaxWidth.negative, event.size.width);
|
|
}
|
|
else {
|
|
this.dataLabelMaxWidth.positive = Math.max(this.dataLabelMaxWidth.positive, event.size.width);
|
|
}
|
|
if (groupIndex === this.results.length - 1) {
|
|
setTimeout(() => this.update());
|
|
}
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarHorizontalStackedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontalStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarHorizontalStackedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarHorizontalStackedComponent, selector: "ngx-charts-bar-horizontal-stacked", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", barPadding: "barPadding", roundDomains: "roundDomains", xScaleMax: "xScaleMax", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[yAxisOffset]="dataLabelMaxWidth.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[activeEntries]="activeEntries"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[activeEntries]="activeEntries"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesHorizontal, selector: "g[ngx-charts-series-horizontal]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "tooltipDisabled", "gradient", "activeEntries", "seriesName", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelWidthChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarHorizontalStackedComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-horizontal-stacked', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[yAxisOffset]="dataLabelMaxWidth.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[activeEntries]="activeEntries"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-horizontal
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[activeEntries]="activeEntries"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class SeriesVerticalComponent {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.type = BarChartType.Standard;
|
|
this.tooltipDisabled = false;
|
|
this.animations = true;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.dataLabelHeightChanged = new EventEmitter();
|
|
this.barsForDataLabels = [];
|
|
this.barOrientation = BarOrientation;
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.updateTooltipSettings();
|
|
let width;
|
|
if (this.series.length) {
|
|
width = this.xScale.bandwidth();
|
|
}
|
|
width = Math.round(width);
|
|
const yScaleMin = Math.max(this.yScale.domain()[0], 0);
|
|
const d0 = {
|
|
[D0Types.positive]: 0,
|
|
[D0Types.negative]: 0
|
|
};
|
|
let d0Type = D0Types.positive;
|
|
let total;
|
|
if (this.type === BarChartType.Normalized) {
|
|
total = this.series.map(d => d.value).reduce((sum, d) => sum + d, 0);
|
|
}
|
|
this.bars = this.series.map((d, index) => {
|
|
let value = d.value;
|
|
const label = this.getLabel(d);
|
|
const formattedLabel = formatLabel(label);
|
|
const roundEdges = this.roundEdges;
|
|
d0Type = value > 0 ? D0Types.positive : D0Types.negative;
|
|
const bar = {
|
|
value,
|
|
label,
|
|
roundEdges,
|
|
data: d,
|
|
width,
|
|
formattedLabel,
|
|
height: 0,
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
if (this.type === BarChartType.Standard) {
|
|
bar.height = Math.abs(this.yScale(value) - this.yScale(yScaleMin));
|
|
bar.x = this.xScale(label);
|
|
if (value < 0) {
|
|
bar.y = this.yScale(0);
|
|
}
|
|
else {
|
|
bar.y = this.yScale(value);
|
|
}
|
|
}
|
|
else if (this.type === BarChartType.Stacked) {
|
|
const offset0 = d0[d0Type];
|
|
const offset1 = offset0 + value;
|
|
d0[d0Type] += value;
|
|
bar.height = this.yScale(offset0) - this.yScale(offset1);
|
|
bar.x = 0;
|
|
bar.y = this.yScale(offset1);
|
|
bar.offset0 = offset0;
|
|
bar.offset1 = offset1;
|
|
}
|
|
else if (this.type === BarChartType.Normalized) {
|
|
let offset0 = d0[d0Type];
|
|
let offset1 = offset0 + value;
|
|
d0[d0Type] += value;
|
|
if (total > 0) {
|
|
offset0 = (offset0 * 100) / total;
|
|
offset1 = (offset1 * 100) / total;
|
|
}
|
|
else {
|
|
offset0 = 0;
|
|
offset1 = 0;
|
|
}
|
|
bar.height = this.yScale(offset0) - this.yScale(offset1);
|
|
bar.x = 0;
|
|
bar.y = this.yScale(offset1);
|
|
bar.offset0 = offset0;
|
|
bar.offset1 = offset1;
|
|
value = (offset1 - offset0).toFixed(2) + '%';
|
|
}
|
|
if (this.colors.scaleType === ScaleType.Ordinal) {
|
|
bar.color = this.colors.getColor(label);
|
|
}
|
|
else {
|
|
if (this.type === BarChartType.Standard) {
|
|
bar.color = this.colors.getColor(value);
|
|
bar.gradientStops = this.colors.getLinearGradientStops(value);
|
|
}
|
|
else {
|
|
bar.color = this.colors.getColor(bar.offset1);
|
|
bar.gradientStops = this.colors.getLinearGradientStops(bar.offset1, bar.offset0);
|
|
}
|
|
}
|
|
let tooltipLabel = formattedLabel;
|
|
bar.ariaLabel = formattedLabel + ' ' + value.toLocaleString();
|
|
if (this.seriesName !== null && this.seriesName !== undefined) {
|
|
tooltipLabel = `${this.seriesName} • ${formattedLabel}`;
|
|
bar.data.series = this.seriesName;
|
|
bar.ariaLabel = this.seriesName + ' ' + bar.ariaLabel;
|
|
}
|
|
bar.tooltipText = this.tooltipDisabled
|
|
? undefined
|
|
: `
|
|
<span class="tooltip-label">${escapeLabel(tooltipLabel)}</span>
|
|
<span class="tooltip-val">${this.dataLabelFormatting ? this.dataLabelFormatting(value) : value.toLocaleString()}</span>
|
|
`;
|
|
return bar;
|
|
});
|
|
this.updateDataLabels();
|
|
}
|
|
updateDataLabels() {
|
|
if (this.type === BarChartType.Stacked) {
|
|
this.barsForDataLabels = [];
|
|
const section = {};
|
|
section.series = this.seriesName;
|
|
const totalPositive = this.series.map(d => d.value).reduce((sum, d) => (d > 0 ? sum + d : sum), 0);
|
|
const totalNegative = this.series.map(d => d.value).reduce((sum, d) => (d < 0 ? sum + d : sum), 0);
|
|
section.total = totalPositive + totalNegative;
|
|
section.x = 0;
|
|
section.y = 0;
|
|
if (section.total > 0) {
|
|
section.height = this.yScale(totalPositive);
|
|
}
|
|
else {
|
|
section.height = this.yScale(totalNegative);
|
|
}
|
|
section.width = this.xScale.bandwidth();
|
|
this.barsForDataLabels.push(section);
|
|
}
|
|
else {
|
|
this.barsForDataLabels = this.series.map(d => {
|
|
const section = {};
|
|
section.series = this.seriesName ?? d.label;
|
|
section.total = d.value;
|
|
section.x = this.xScale(d.label);
|
|
section.y = this.yScale(0);
|
|
section.height = this.yScale(section.total) - this.yScale(0);
|
|
section.width = this.xScale.bandwidth();
|
|
return section;
|
|
});
|
|
}
|
|
}
|
|
updateTooltipSettings() {
|
|
this.tooltipPlacement = this.tooltipDisabled ? undefined : PlacementTypes.Top;
|
|
this.tooltipType = this.tooltipDisabled ? undefined : StyleTypes.tooltip;
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(active => {
|
|
return entry.name === active.name && entry.value === active.value;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
getLabel(dataItem) {
|
|
if (dataItem.label) {
|
|
return dataItem.label;
|
|
}
|
|
return dataItem.name;
|
|
}
|
|
trackBy(index, bar) {
|
|
return bar.label;
|
|
}
|
|
trackDataLabelBy(index, barLabel) {
|
|
return index + '#' + barLabel.series + '#' + barLabel.total;
|
|
}
|
|
}
|
|
SeriesVerticalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SeriesVerticalComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
SeriesVerticalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: SeriesVerticalComponent, selector: "g[ngx-charts-series-vertical]", inputs: { dims: "dims", type: "type", series: "series", xScale: "xScale", yScale: "yScale", colors: "colors", gradient: "gradient", activeEntries: "activeEntries", seriesName: "seriesName", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate", roundEdges: "roundEdges", animations: "animations", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate", dataLabelHeightChanged: "dataLabelHeightChanged" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
ngx-charts-bar
|
|
*ngFor="let bar of bars; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[@.disabled]="!animations"
|
|
[width]="bar.width"
|
|
[height]="bar.height"
|
|
[x]="bar.x"
|
|
[y]="bar.y"
|
|
[fill]="bar.color"
|
|
[stops]="bar.gradientStops"
|
|
[data]="bar.data"
|
|
[orientation]="barOrientation.Vertical"
|
|
[roundEdges]="bar.roundEdges"
|
|
[gradient]="gradient"
|
|
[ariaLabel]="bar.ariaLabel"
|
|
[isActive]="isActive(bar.data)"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="bar.data"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
ngx-charts-bar
|
|
*ngFor="let bar of bars; trackBy: trackBy"
|
|
[width]="bar.width"
|
|
[height]="bar.height"
|
|
[x]="bar.x"
|
|
[y]="bar.y"
|
|
[fill]="bar.color"
|
|
[stops]="bar.gradientStops"
|
|
[data]="bar.data"
|
|
[orientation]="barOrientation.Vertical"
|
|
[roundEdges]="bar.roundEdges"
|
|
[gradient]="gradient"
|
|
[ariaLabel]="bar.ariaLabel"
|
|
[isActive]="isActive(bar.data)"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="bar.data"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="showDataLabel">
|
|
<svg:g
|
|
ngx-charts-bar-label
|
|
*ngFor="let b of barsForDataLabels; let i = index; trackBy: trackDataLabelBy"
|
|
[barX]="b.x"
|
|
[barY]="b.y"
|
|
[barWidth]="b.width"
|
|
[barHeight]="b.height"
|
|
[value]="b.total"
|
|
[valueFormatting]="dataLabelFormatting"
|
|
[orientation]="barOrientation.Vertical"
|
|
(dimensionsChanged)="dataLabelHeightChanged.emit({ size: $event, index: i })"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: BarComponent, selector: "g[ngx-charts-bar]", inputs: ["fill", "data", "width", "height", "x", "y", "orientation", "roundEdges", "gradient", "offset", "isActive", "stops", "animations", "ariaLabel", "noBarWhenZero"], outputs: ["select", "activate", "deactivate"] }, { type: BarLabelComponent, selector: "g[ngx-charts-bar-label]", inputs: ["value", "valueFormatting", "barX", "barY", "barWidth", "barHeight", "orientation"], outputs: ["dimensionsChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SeriesVerticalComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-series-vertical]',
|
|
template: `
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
ngx-charts-bar
|
|
*ngFor="let bar of bars; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[@.disabled]="!animations"
|
|
[width]="bar.width"
|
|
[height]="bar.height"
|
|
[x]="bar.x"
|
|
[y]="bar.y"
|
|
[fill]="bar.color"
|
|
[stops]="bar.gradientStops"
|
|
[data]="bar.data"
|
|
[orientation]="barOrientation.Vertical"
|
|
[roundEdges]="bar.roundEdges"
|
|
[gradient]="gradient"
|
|
[ariaLabel]="bar.ariaLabel"
|
|
[isActive]="isActive(bar.data)"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="bar.data"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
ngx-charts-bar
|
|
*ngFor="let bar of bars; trackBy: trackBy"
|
|
[width]="bar.width"
|
|
[height]="bar.height"
|
|
[x]="bar.x"
|
|
[y]="bar.y"
|
|
[fill]="bar.color"
|
|
[stops]="bar.gradientStops"
|
|
[data]="bar.data"
|
|
[orientation]="barOrientation.Vertical"
|
|
[roundEdges]="bar.roundEdges"
|
|
[gradient]="gradient"
|
|
[ariaLabel]="bar.ariaLabel"
|
|
[isActive]="isActive(bar.data)"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="bar.data"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="showDataLabel">
|
|
<svg:g
|
|
ngx-charts-bar-label
|
|
*ngFor="let b of barsForDataLabels; let i = index; trackBy: trackDataLabelBy"
|
|
[barX]="b.x"
|
|
[barY]="b.y"
|
|
[barWidth]="b.width"
|
|
[barHeight]="b.height"
|
|
[value]="b.total"
|
|
[valueFormatting]="dataLabelFormatting"
|
|
[orientation]="barOrientation.Vertical"
|
|
(dimensionsChanged)="dataLabelHeightChanged.emit({ size: $event, index: i })"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { dims: [{
|
|
type: Input
|
|
}], type: [{
|
|
type: Input
|
|
}], series: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], seriesName: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], dataLabelHeightChanged: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class BarVerticalComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.roundEdges = true;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showDataLabel) {
|
|
this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
|
}
|
|
this.margin = [10 + this.dataLabelMaxHeight.positive, 20, 10 + this.dataLabelMaxHeight.negative, 20];
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
if (this.showDataLabel) {
|
|
this.dims.height -= this.dataLabelMaxHeight.negative;
|
|
}
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0] + this.dataLabelMaxHeight.negative})`;
|
|
}
|
|
getXScale() {
|
|
this.xDomain = this.getXDomain();
|
|
const spacing = this.xDomain.length / (this.dims.width / this.barPadding + 1);
|
|
return scaleBand().range([0, this.dims.width]).paddingInner(spacing).domain(this.xDomain);
|
|
}
|
|
getYScale() {
|
|
this.yDomain = this.getYDomain();
|
|
const scale = scaleLinear().range([this.dims.height, 0]).domain(this.yDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getXDomain() {
|
|
return this.results.map(d => d.label);
|
|
}
|
|
getYDomain() {
|
|
const values = this.results.map(d => d.value);
|
|
let min = this.yScaleMin ? Math.min(this.yScaleMin, ...values) : Math.min(0, ...values);
|
|
if (this.yAxisTicks && !this.yAxisTicks.some(isNaN)) {
|
|
min = Math.min(min, ...this.yAxisTicks);
|
|
}
|
|
let max = this.yScaleMax ? Math.max(this.yScaleMax, ...values) : Math.max(0, ...values);
|
|
if (this.yAxisTicks && !this.yAxisTicks.some(isNaN)) {
|
|
max = Math.max(max, ...this.yAxisTicks);
|
|
}
|
|
return [min, max];
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.xDomain;
|
|
}
|
|
else {
|
|
domain = this.yDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.xDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.yDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onDataLabelMaxHeightChanged(event) {
|
|
if (event.size.negative) {
|
|
this.dataLabelMaxHeight.negative = Math.max(this.dataLabelMaxHeight.negative, event.size.height);
|
|
}
|
|
else {
|
|
this.dataLabelMaxHeight.positive = Math.max(this.dataLabelMaxHeight.positive, event.size.height);
|
|
}
|
|
if (event.index === this.results.length - 1) {
|
|
setTimeout(() => this.update());
|
|
}
|
|
}
|
|
onActivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarVerticalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVerticalComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarVerticalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarVerticalComponent, selector: "ngx-charts-bar-vertical", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", barPadding: "barPadding", roundDomains: "roundDomains", roundEdges: "roundEdges", yScaleMax: "yScaleMax", yScaleMin: "yScaleMin", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, true)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[xAxisOffset]="dataLabelMaxHeight.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="results"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[activeEntries]="activeEntries"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
(select)="onClick($event)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesVerticalComponent, selector: "g[ngx-charts-series-vertical]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "gradient", "activeEntries", "seriesName", "tooltipDisabled", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelHeightChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVerticalComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-vertical', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, true)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[xAxisOffset]="dataLabelMaxHeight.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[series]="results"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[activeEntries]="activeEntries"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
(select)="onClick($event)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], yScaleMin: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarVertical2DComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.scaleType = ScaleType.Ordinal;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.groupPadding = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.roundEdges = true;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
|
this.isSSR = false;
|
|
this.barOrientation = BarOrientation;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showDataLabel) {
|
|
this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
|
}
|
|
this.margin = [10 + this.dataLabelMaxHeight.positive, 20, 10 + this.dataLabelMaxHeight.negative, 20];
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.showDataLabel) {
|
|
this.dims.height -= this.dataLabelMaxHeight.negative;
|
|
}
|
|
this.formatDates();
|
|
this.groupDomain = this.getGroupDomain();
|
|
this.innerDomain = this.getInnerDomain();
|
|
this.valueDomain = this.getValueDomain();
|
|
this.groupScale = this.getGroupScale();
|
|
this.innerScale = this.getInnerScale();
|
|
this.valueScale = this.getValueScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0] + this.dataLabelMaxHeight.negative})`;
|
|
}
|
|
onDataLabelMaxHeightChanged(event, groupIndex) {
|
|
if (event.size.negative) {
|
|
this.dataLabelMaxHeight.negative = Math.max(this.dataLabelMaxHeight.negative, event.size.height);
|
|
}
|
|
else {
|
|
this.dataLabelMaxHeight.positive = Math.max(this.dataLabelMaxHeight.positive, event.size.height);
|
|
}
|
|
if (groupIndex === this.results.length - 1) {
|
|
setTimeout(() => this.update());
|
|
}
|
|
}
|
|
getGroupScale() {
|
|
const spacing = this.groupDomain.length / (this.dims.height / this.groupPadding + 1);
|
|
return scaleBand()
|
|
.rangeRound([0, this.dims.width])
|
|
.paddingInner(spacing)
|
|
.paddingOuter(spacing / 2)
|
|
.domain(this.groupDomain);
|
|
}
|
|
getInnerScale() {
|
|
const width = this.groupScale.bandwidth();
|
|
const spacing = this.innerDomain.length / (width / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, width]).paddingInner(spacing).domain(this.innerDomain);
|
|
}
|
|
getValueScale() {
|
|
const scale = scaleLinear().range([this.dims.height, 0]).domain(this.valueDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getGroupDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.label)) {
|
|
domain.push(group.label);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getInnerDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.label)) {
|
|
domain.push(d.label);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getValueDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.value)) {
|
|
domain.push(d.value);
|
|
}
|
|
}
|
|
}
|
|
const min = Math.min(0, ...domain);
|
|
const max = this.yScaleMax ? Math.max(this.yScaleMax, ...domain) : Math.max(0, ...domain);
|
|
return [min, max];
|
|
}
|
|
groupTransform(group) {
|
|
return `translate(${this.groupScale(group.label)}, 0)`;
|
|
}
|
|
onClick(data, group) {
|
|
if (group) {
|
|
data.series = group.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.innerDomain;
|
|
}
|
|
else {
|
|
domain = this.valueDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.innerDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.valueDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarVertical2DComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVertical2DComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarVertical2DComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarVertical2DComponent, selector: "ngx-charts-bar-vertical-2d", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", scaleType: "scaleType", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", groupPadding: "groupPadding", barPadding: "barPadding", roundDomains: "roundDomains", roundEdges: "roundEdges", yScaleMax: "yScaleMax", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-grid-panel-series
|
|
[xScale]="groupScale"
|
|
[yScale]="valueScale"
|
|
[data]="results"
|
|
[dims]="dims"
|
|
[orient]="barOrientation.Vertical"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="groupScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[xAxisOffset]="dataLabelMaxHeight.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="valueScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
[activeEntries]="activeEntries"
|
|
[xScale]="innerScale"
|
|
[yScale]="valueScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
[activeEntries]="activeEntries"
|
|
[xScale]="innerScale"
|
|
[yScale]="valueScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: GridPanelSeriesComponent, selector: "g[ngx-charts-grid-panel-series]", inputs: ["data", "dims", "xScale", "yScale", "orient"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesVerticalComponent, selector: "g[ngx-charts-series-vertical]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "gradient", "activeEntries", "seriesName", "tooltipDisabled", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelHeightChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVertical2DComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-vertical-2d', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-grid-panel-series
|
|
[xScale]="groupScale"
|
|
[yScale]="valueScale"
|
|
[data]="results"
|
|
[dims]="dims"
|
|
[orient]="barOrientation.Vertical"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="groupScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[xAxisOffset]="dataLabelMaxHeight.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="valueScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
[activeEntries]="activeEntries"
|
|
[xScale]="innerScale"
|
|
[yScale]="valueScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
[activeEntries]="activeEntries"
|
|
[xScale]="innerScale"
|
|
[yScale]="valueScale"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[roundEdges]="roundEdges"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], scaleType: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], groupPadding: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarVerticalNormalizedComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.valueDomain = [0, 100];
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.isSSR = false;
|
|
this.barChartType = BarChartType;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
this.groupDomain = this.getGroupDomain();
|
|
this.innerDomain = this.getInnerDomain();
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getGroupDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.label)) {
|
|
domain.push(group.label);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getInnerDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.label)) {
|
|
domain.push(d.label);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getXScale() {
|
|
const spacing = this.groupDomain.length / (this.dims.width / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, this.dims.width]).paddingInner(spacing).domain(this.groupDomain);
|
|
}
|
|
getYScale() {
|
|
const scale = scaleLinear().range([this.dims.height, 0]).domain(this.valueDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
groupTransform(group) {
|
|
return `translate(${this.xScale(group.name)}, 0)`;
|
|
}
|
|
onClick(data, group) {
|
|
if (group) {
|
|
data.series = group.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.innerDomain;
|
|
}
|
|
else {
|
|
domain = this.valueDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.innerDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.valueDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarVerticalNormalizedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVerticalNormalizedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarVerticalNormalizedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarVerticalNormalizedComponent, selector: "ngx-charts-bar-vertical-normalized", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", barPadding: "barPadding", roundDomains: "roundDomains", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g *ngFor="let group of results; trackBy: trackBy" [attr.transform]="groupTransform(group)">
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesVerticalComponent, selector: "g[ngx-charts-series-vertical]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "gradient", "activeEntries", "seriesName", "tooltipDisabled", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelHeightChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVerticalNormalizedComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-vertical-normalized', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g *ngFor="let group of results; trackBy: trackBy" [attr.transform]="groupTransform(group)">
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Normalized"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarVerticalStackedComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.tooltipDisabled = false;
|
|
this.showGridLines = true;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.barPadding = 8;
|
|
this.roundDomains = false;
|
|
this.showDataLabel = false;
|
|
this.noBarWhenZero = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
|
this.isSSR = false;
|
|
this.barChartType = BarChartType;
|
|
this.trackBy = (index, item) => {
|
|
return item.name;
|
|
};
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showDataLabel) {
|
|
this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
|
}
|
|
this.margin = [10 + this.dataLabelMaxHeight.positive, 20, 10 + this.dataLabelMaxHeight.negative, 20];
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.showDataLabel) {
|
|
this.dims.height -= this.dataLabelMaxHeight.negative;
|
|
}
|
|
this.formatDates();
|
|
this.groupDomain = this.getGroupDomain();
|
|
this.innerDomain = this.getInnerDomain();
|
|
this.valueDomain = this.getValueDomain();
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0] + this.dataLabelMaxHeight.negative})`;
|
|
}
|
|
getGroupDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.label)) {
|
|
domain.push(group.label);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getInnerDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.label)) {
|
|
domain.push(d.label);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getValueDomain() {
|
|
const domain = [];
|
|
let smallest = 0;
|
|
let biggest = 0;
|
|
for (const group of this.results) {
|
|
let smallestSum = 0;
|
|
let biggestSum = 0;
|
|
for (const d of group.series) {
|
|
if (d.value < 0) {
|
|
smallestSum += d.value;
|
|
}
|
|
else {
|
|
biggestSum += d.value;
|
|
}
|
|
smallest = d.value < smallest ? d.value : smallest;
|
|
biggest = d.value > biggest ? d.value : biggest;
|
|
}
|
|
domain.push(smallestSum);
|
|
domain.push(biggestSum);
|
|
}
|
|
domain.push(smallest);
|
|
domain.push(biggest);
|
|
const min = Math.min(0, ...domain);
|
|
const max = this.yScaleMax ? Math.max(this.yScaleMax, ...domain) : Math.max(...domain);
|
|
return [min, max];
|
|
}
|
|
getXScale() {
|
|
const spacing = this.groupDomain.length / (this.dims.width / this.barPadding + 1);
|
|
return scaleBand().rangeRound([0, this.dims.width]).paddingInner(spacing).domain(this.groupDomain);
|
|
}
|
|
getYScale() {
|
|
const scale = scaleLinear().range([this.dims.height, 0]).domain(this.valueDomain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
onDataLabelMaxHeightChanged(event, groupIndex) {
|
|
if (event.size.negative) {
|
|
this.dataLabelMaxHeight.negative = Math.max(this.dataLabelMaxHeight.negative, event.size.height);
|
|
}
|
|
else {
|
|
this.dataLabelMaxHeight.positive = Math.max(this.dataLabelMaxHeight.positive, event.size.height);
|
|
}
|
|
if (groupIndex === this.results.length - 1) {
|
|
setTimeout(() => this.update());
|
|
}
|
|
}
|
|
groupTransform(group) {
|
|
return `translate(${this.xScale(group.name) || 0}, 0)`;
|
|
}
|
|
onClick(data, group) {
|
|
if (group) {
|
|
data.series = group.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.innerDomain;
|
|
}
|
|
else {
|
|
domain = this.valueDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.innerDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.valueDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
BarVerticalStackedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVerticalStackedComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BarVerticalStackedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BarVerticalStackedComponent, selector: "ngx-charts-bar-vertical-stacked", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", gradient: "gradient", showGridLines: "showGridLines", activeEntries: "activeEntries", schemeType: "schemeType", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", barPadding: "barPadding", roundDomains: "roundDomains", yScaleMax: "yScaleMax", showDataLabel: "showDataLabel", dataLabelFormatting: "dataLabelFormatting", noBarWhenZero: "noBarWhenZero", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[xAxisOffset]="dataLabelMaxHeight.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: SeriesVerticalComponent, selector: "g[ngx-charts-series-vertical]", inputs: ["dims", "type", "series", "xScale", "yScale", "colors", "gradient", "activeEntries", "seriesName", "tooltipDisabled", "tooltipTemplate", "roundEdges", "animations", "showDataLabel", "dataLabelFormatting", "noBarWhenZero"], outputs: ["select", "activate", "deactivate", "dataLabelHeightChanged"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarVerticalStackedComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bar-vertical-stacked', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, undefined, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="bar-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[xAxisOffset]="dataLabelMaxHeight.negative"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[@animationState]="'active'"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g
|
|
*ngFor="let group of results; let index = index; trackBy: trackBy"
|
|
[attr.transform]="groupTransform(group)"
|
|
>
|
|
<svg:g
|
|
ngx-charts-series-vertical
|
|
[type]="barChartType.Stacked"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[activeEntries]="activeEntries"
|
|
[colors]="colors"
|
|
[series]="group.series"
|
|
[dims]="dims"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[showDataLabel]="showDataLabel"
|
|
[dataLabelFormatting]="dataLabelFormatting"
|
|
[seriesName]="group.name"
|
|
[animations]="animations"
|
|
[noBarWhenZero]="noBarWhenZero"
|
|
(select)="onClick($event, group)"
|
|
(activate)="onActivate($event, group)"
|
|
(deactivate)="onDeactivate($event, group)"
|
|
(dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1,
|
|
transform: '*'
|
|
}),
|
|
animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], barPadding: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], showDataLabel: [{
|
|
type: Input
|
|
}], dataLabelFormatting: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class BarChartModule {
|
|
}
|
|
BarChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
BarChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarChartModule, declarations: [BarComponent,
|
|
BarHorizontalComponent,
|
|
BarHorizontal2DComponent,
|
|
BarHorizontalNormalizedComponent,
|
|
BarHorizontalStackedComponent,
|
|
BarVerticalComponent,
|
|
BarVertical2DComponent,
|
|
BarVerticalNormalizedComponent,
|
|
BarVerticalStackedComponent,
|
|
BarLabelComponent,
|
|
SeriesHorizontal,
|
|
SeriesVerticalComponent], imports: [ChartCommonModule], exports: [BarComponent,
|
|
BarHorizontalComponent,
|
|
BarHorizontal2DComponent,
|
|
BarHorizontalNormalizedComponent,
|
|
BarHorizontalStackedComponent,
|
|
BarVerticalComponent,
|
|
BarVertical2DComponent,
|
|
BarVerticalNormalizedComponent,
|
|
BarVerticalStackedComponent,
|
|
BarLabelComponent,
|
|
SeriesHorizontal,
|
|
SeriesVerticalComponent] });
|
|
BarChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarChartModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BarChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [
|
|
BarComponent,
|
|
BarHorizontalComponent,
|
|
BarHorizontal2DComponent,
|
|
BarHorizontalNormalizedComponent,
|
|
BarHorizontalStackedComponent,
|
|
BarVerticalComponent,
|
|
BarVertical2DComponent,
|
|
BarVerticalNormalizedComponent,
|
|
BarVerticalStackedComponent,
|
|
BarLabelComponent,
|
|
SeriesHorizontal,
|
|
SeriesVerticalComponent
|
|
],
|
|
exports: [
|
|
BarComponent,
|
|
BarHorizontalComponent,
|
|
BarHorizontal2DComponent,
|
|
BarHorizontalNormalizedComponent,
|
|
BarHorizontalStackedComponent,
|
|
BarVerticalComponent,
|
|
BarVertical2DComponent,
|
|
BarVerticalNormalizedComponent,
|
|
BarVerticalStackedComponent,
|
|
BarLabelComponent,
|
|
SeriesHorizontal,
|
|
SeriesVerticalComponent
|
|
]
|
|
}]
|
|
}] });
|
|
|
|
const cloneDeep = rfdc();
|
|
class BoxComponent {
|
|
constructor(element, cd) {
|
|
this.cd = cd;
|
|
this.roundEdges = true;
|
|
this.gradient = false;
|
|
this.offset = 0;
|
|
this.isActive = false;
|
|
this.animations = true;
|
|
this.noBarWhenZero = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.BarOrientation = BarOrientation;
|
|
this.initialized = false;
|
|
this.hasGradient = false;
|
|
this.hideBar = false;
|
|
this.nativeElm = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
if (!this.initialized) {
|
|
this.loadAnimation();
|
|
this.initialized = true;
|
|
}
|
|
else {
|
|
this.update();
|
|
}
|
|
}
|
|
update() {
|
|
this.boxStrokeWidth = Math.max(this.strokeWidth, 1);
|
|
this.whiskerStrokeWidth = Math.max(this.strokeWidth / 2, 1);
|
|
this.medianLineWidth = 1.5 * this.strokeWidth;
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientFill = `url(#${this.gradientId})`;
|
|
if (this.gradient) {
|
|
this.gradientStops = this.getGradient();
|
|
this.hasGradient = true;
|
|
}
|
|
else {
|
|
this.hasGradient = false;
|
|
}
|
|
this.updateLineEl();
|
|
this.updatePathEl();
|
|
this.checkToHideBar();
|
|
this.maskLineId = 'mask' + id().toString();
|
|
this.maskLine = `url(#${this.maskLineId})`;
|
|
if (this.cd) {
|
|
this.cd.markForCheck();
|
|
}
|
|
}
|
|
loadAnimation() {
|
|
this.boxPath = this.oldPath = this.getStartingPath();
|
|
this.oldLineCoordinates = this.getStartingLineCoordinates();
|
|
setTimeout(this.update.bind(this), 100);
|
|
}
|
|
updatePathEl() {
|
|
const nodeBar = select(this.nativeElm).selectAll('.bar');
|
|
const path = this.getPath();
|
|
if (this.animations) {
|
|
nodeBar
|
|
.attr('d', this.oldPath)
|
|
.transition()
|
|
.ease(easeSinInOut)
|
|
.duration(500)
|
|
.attrTween('d', this.pathTween(path, 4));
|
|
}
|
|
else {
|
|
nodeBar.attr('d', path);
|
|
}
|
|
this.oldPath = path;
|
|
}
|
|
updateLineEl() {
|
|
const lineEl = select(this.nativeElm).selectAll('.bar-line');
|
|
const lineCoordinates = this.lineCoordinates;
|
|
const oldLineCoordinates = this.oldLineCoordinates;
|
|
if (this.animations) {
|
|
lineEl
|
|
.attr('x1', (_, index) => oldLineCoordinates[index].v1.x)
|
|
.attr('y1', (_, index) => oldLineCoordinates[index].v1.y)
|
|
.attr('x2', (_, index) => oldLineCoordinates[index].v2.x)
|
|
.attr('y2', (_, index) => oldLineCoordinates[index].v2.y)
|
|
.transition()
|
|
.ease(easeSinInOut)
|
|
.duration(500)
|
|
.attr('x1', (_, index) => lineCoordinates[index].v1.x)
|
|
.attr('y1', (_, index) => lineCoordinates[index].v1.y)
|
|
.attr('x2', (_, index) => lineCoordinates[index].v2.x)
|
|
.attr('y2', (_, index) => lineCoordinates[index].v2.y);
|
|
}
|
|
else {
|
|
lineEl
|
|
.attr('x1', (_, index) => lineCoordinates[index].v1.x)
|
|
.attr('y1', (_, index) => lineCoordinates[index].v1.y)
|
|
.attr('x2', (_, index) => lineCoordinates[index].v2.x)
|
|
.attr('y2', (_, index) => lineCoordinates[index].v2.y);
|
|
}
|
|
this.oldLineCoordinates = [...lineCoordinates];
|
|
}
|
|
/**
|
|
* See [D3 Selections](https://www.d3indepth.com/selections/)
|
|
* @param d The joined data.
|
|
* @param index The index of the element within the selection
|
|
* @param node The node element (Line).
|
|
*/
|
|
lineTween(attr, d, index, node) {
|
|
const nodeLineEl = node[index];
|
|
return nodeLineEl[attr].baseVal.value;
|
|
}
|
|
// TODO: Refactor into another .ts file if https://github.com/swimlane/ngx-charts/pull/1179 gets merged.
|
|
pathTween(d1, precision) {
|
|
return function () {
|
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
const path0 = this;
|
|
const path1 = this.cloneNode();
|
|
path1.setAttribute('d', d1);
|
|
const n0 = path0?.getTotalLength();
|
|
const n1 = path1?.getTotalLength();
|
|
// Uniform sampling of distance based on specified precision.
|
|
const distances = [0];
|
|
let i = 0;
|
|
const dt = precision / Math.max(n0, n1);
|
|
while (i < 1) {
|
|
distances.push(i);
|
|
i += dt;
|
|
}
|
|
distances.push(1);
|
|
// Compute point-interpolators at each distance.
|
|
const points = distances.map((t) => {
|
|
const p0 = path0.getPointAtLength(t * n0);
|
|
const p1 = path1.getPointAtLength(t * n1);
|
|
return interpolate([p0.x, p0.y], [p1.x, p1.y]);
|
|
});
|
|
// 't': T is the fraction of time (between 0 and 1) since the transition began.
|
|
return (t) => {
|
|
return t < 1 ? 'M' + points.map((p) => p(t)).join('L') : d1;
|
|
};
|
|
};
|
|
}
|
|
getStartingPath() {
|
|
if (!this.animations) {
|
|
return this.getPath();
|
|
}
|
|
const radius = this.roundEdges ? 1 : 0;
|
|
const { x, y } = this.lineCoordinates[2].v1;
|
|
return roundedRect(x - this.width, y - 1, this.width, 2, radius, this.edges);
|
|
}
|
|
getPath() {
|
|
const radius = this.getRadius();
|
|
let path = '';
|
|
path = roundedRect(this.x, this.y, this.width, this.height, Math.min(this.height, radius), this.edges);
|
|
return path;
|
|
}
|
|
getStartingLineCoordinates() {
|
|
if (!this.animations) {
|
|
return [...this.lineCoordinates];
|
|
}
|
|
const lineCoordinates = cloneDeep(this.lineCoordinates);
|
|
lineCoordinates[1].v1.y = lineCoordinates[1].v2.y = lineCoordinates[3].v1.y = lineCoordinates[3].v2.y = lineCoordinates[0].v1.y = lineCoordinates[0].v2.y =
|
|
lineCoordinates[2].v1.y;
|
|
return lineCoordinates;
|
|
}
|
|
getRadius() {
|
|
let radius = 0;
|
|
if (this.roundEdges && this.height > 5 && this.width > 5) {
|
|
radius = Math.floor(Math.min(5, this.height / 2, this.width / 2));
|
|
}
|
|
return radius;
|
|
}
|
|
getGradient() {
|
|
return [
|
|
{
|
|
offset: 0,
|
|
color: this.fill,
|
|
opacity: this.getStartOpacity()
|
|
},
|
|
{
|
|
offset: 100,
|
|
color: this.fill,
|
|
opacity: 1
|
|
}
|
|
];
|
|
}
|
|
getStartOpacity() {
|
|
if (this.roundEdges) {
|
|
return 0.2;
|
|
}
|
|
else {
|
|
return 0.5;
|
|
}
|
|
}
|
|
get edges() {
|
|
let edges = [false, false, false, false];
|
|
if (this.roundEdges) {
|
|
edges = [true, true, true, true];
|
|
}
|
|
return edges;
|
|
}
|
|
onMouseEnter() {
|
|
this.activate.emit(this.data);
|
|
}
|
|
onMouseLeave() {
|
|
this.deactivate.emit(this.data);
|
|
}
|
|
checkToHideBar() {
|
|
this.hideBar = this.noBarWhenZero && this.height === 0;
|
|
}
|
|
}
|
|
BoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
BoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BoxComponent, selector: "g[ngx-charts-box]", inputs: { strokeColor: "strokeColor", strokeWidth: "strokeWidth", fill: "fill", data: "data", width: "width", height: "height", x: "x", y: "y", lineCoordinates: "lineCoordinates", roundEdges: "roundEdges", gradient: "gradient", gradientStops: "gradientStops", offset: "offset", isActive: "isActive", animations: "animations", ariaLabel: "ariaLabel", noBarWhenZero: "noBarWhenZero" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:defs>
|
|
<svg:g
|
|
*ngIf="hasGradient"
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="BarOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
<svg:mask [attr.id]="maskLineId">
|
|
<svg:g>
|
|
<rect height="100%" width="100%" fill="white" fill-opacity="1" />
|
|
<path class="bar" [attr.d]="boxPath" fill="black" fill-opacity="1" />
|
|
</svg:g>
|
|
</svg:mask>
|
|
</svg:defs>
|
|
<svg:g>
|
|
<svg:path
|
|
class="bar"
|
|
role="img"
|
|
tabIndex="-1"
|
|
[class.active]="isActive"
|
|
[class.hidden]="hideBar"
|
|
[attr.d]="boxPath"
|
|
[attr.stroke]="strokeColor"
|
|
[attr.stroke-width]="boxStrokeWidth"
|
|
[attr.aria-label]="ariaLabel"
|
|
[attr.fill]="hasGradient ? gradientFill : fill"
|
|
(click)="select.emit(data)"
|
|
/>
|
|
<svg:line
|
|
*ngFor="let line of lineCoordinates; let i = index"
|
|
class="bar-line"
|
|
[class.hidden]="hideBar"
|
|
[attr.x1]="line.v1.x"
|
|
[attr.y1]="line.v1.y"
|
|
[attr.x2]="line.v2.x"
|
|
[attr.y2]="line.v2.y"
|
|
[attr.stroke]="strokeColor"
|
|
[attr.stroke-width]="i === 2 ? medianLineWidth : whiskerStrokeWidth"
|
|
[attr.mask]="i ? undefined : maskLine"
|
|
fill="none"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-box]',
|
|
template: `
|
|
<svg:defs>
|
|
<svg:g
|
|
*ngIf="hasGradient"
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="BarOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
<svg:mask [attr.id]="maskLineId">
|
|
<svg:g>
|
|
<rect height="100%" width="100%" fill="white" fill-opacity="1" />
|
|
<path class="bar" [attr.d]="boxPath" fill="black" fill-opacity="1" />
|
|
</svg:g>
|
|
</svg:mask>
|
|
</svg:defs>
|
|
<svg:g>
|
|
<svg:path
|
|
class="bar"
|
|
role="img"
|
|
tabIndex="-1"
|
|
[class.active]="isActive"
|
|
[class.hidden]="hideBar"
|
|
[attr.d]="boxPath"
|
|
[attr.stroke]="strokeColor"
|
|
[attr.stroke-width]="boxStrokeWidth"
|
|
[attr.aria-label]="ariaLabel"
|
|
[attr.fill]="hasGradient ? gradientFill : fill"
|
|
(click)="select.emit(data)"
|
|
/>
|
|
<svg:line
|
|
*ngFor="let line of lineCoordinates; let i = index"
|
|
class="bar-line"
|
|
[class.hidden]="hideBar"
|
|
[attr.x1]="line.v1.x"
|
|
[attr.y1]="line.v1.y"
|
|
[attr.x2]="line.v2.x"
|
|
[attr.y2]="line.v2.y"
|
|
[attr.stroke]="strokeColor"
|
|
[attr.stroke-width]="i === 2 ? medianLineWidth : whiskerStrokeWidth"
|
|
[attr.mask]="i ? undefined : maskLine"
|
|
fill="none"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { strokeColor: [{
|
|
type: Input
|
|
}], strokeWidth: [{
|
|
type: Input
|
|
}], fill: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], x: [{
|
|
type: Input
|
|
}], y: [{
|
|
type: Input
|
|
}], lineCoordinates: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], gradientStops: [{
|
|
type: Input
|
|
}], offset: [{
|
|
type: Input
|
|
}], isActive: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], ariaLabel: [{
|
|
type: Input
|
|
}], noBarWhenZero: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], onMouseEnter: [{
|
|
type: HostListener,
|
|
args: ['mouseenter']
|
|
}], onMouseLeave: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class BoxSeriesComponent {
|
|
constructor() {
|
|
this.animations = true;
|
|
this.tooltipDisabled = false;
|
|
this.gradient = false;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
update() {
|
|
this.updateTooltipSettings();
|
|
const width = this.series && this.series.series.length ? Math.round(this.xScale.bandwidth()) : null;
|
|
const seriesName = this.series.name;
|
|
// Calculate Quantile and Whiskers for each box serie.
|
|
this.counts = this.series.series;
|
|
const mappedCounts = this.counts.map(serie => Number(serie.value));
|
|
this.whiskers = [min(mappedCounts), max(mappedCounts)];
|
|
// We get the group count and must sort it in order to retrieve quantiles.
|
|
const groupCounts = this.counts.map(item => item.value).sort((a, b) => Number(a) - Number(b));
|
|
this.quartiles = this.getBoxQuantiles(groupCounts);
|
|
this.lineCoordinates = this.getLinesCoordinates(seriesName.toString(), this.whiskers, this.quartiles, width);
|
|
const value = this.quartiles[1];
|
|
const formattedLabel = formatLabel(seriesName);
|
|
const box = {
|
|
value,
|
|
data: this.counts,
|
|
label: seriesName,
|
|
formattedLabel,
|
|
width,
|
|
height: 0,
|
|
x: 0,
|
|
y: 0,
|
|
roundEdges: this.roundEdges,
|
|
quartiles: this.quartiles,
|
|
lineCoordinates: this.lineCoordinates
|
|
};
|
|
box.height = Math.abs(this.yScale(this.quartiles[0]) - this.yScale(this.quartiles[2]));
|
|
box.x = this.xScale(seriesName.toString());
|
|
box.y = this.yScale(this.quartiles[2]);
|
|
box.ariaLabel = formattedLabel + ' - Median: ' + value.toLocaleString();
|
|
if (this.colors.scaleType === ScaleType.Ordinal) {
|
|
box.color = this.colors.getColor(seriesName);
|
|
}
|
|
else {
|
|
box.color = this.colors.getColor(this.quartiles[1]);
|
|
box.gradientStops = this.colors.getLinearGradientStops(this.quartiles[0], this.quartiles[2]);
|
|
}
|
|
const tooltipLabel = formattedLabel;
|
|
const formattedTooltipLabel = `
|
|
<span class="tooltip-label">${escapeLabel(tooltipLabel)}</span>
|
|
<span class="tooltip-val">
|
|
• Q1: ${this.quartiles[0]} • Q2: ${this.quartiles[1]} • Q3: ${this.quartiles[2]}<br>
|
|
• Min: ${this.whiskers[0]} • Max: ${this.whiskers[1]}
|
|
</span>`;
|
|
box.tooltipText = this.tooltipDisabled ? undefined : formattedTooltipLabel;
|
|
this.tooltipTitle = this.tooltipDisabled ? undefined : box.tooltipText;
|
|
this.box = box;
|
|
}
|
|
getBoxQuantiles(inputData) {
|
|
return [quantile(inputData, 0.25), quantile(inputData, 0.5), quantile(inputData, 0.75)];
|
|
}
|
|
getLinesCoordinates(seriesName, whiskers, quartiles, barWidth) {
|
|
// The X value is not being centered, so had to sum half the width to align it.
|
|
const commonX = this.xScale(seriesName);
|
|
const offsetX = commonX + barWidth / 2;
|
|
const medianLineWidth = Math.max(barWidth + 4 * this.strokeWidth, 1);
|
|
const whiskerLineWidth = Math.max(barWidth / 3, 1);
|
|
const whiskerZero = this.yScale(whiskers[0]);
|
|
const whiskerOne = this.yScale(whiskers[1]);
|
|
const median = this.yScale(quartiles[1]);
|
|
const topLine = {
|
|
v1: { x: offsetX + whiskerLineWidth / 2, y: whiskerZero },
|
|
v2: { x: offsetX - whiskerLineWidth / 2, y: whiskerZero }
|
|
};
|
|
const medianLine = {
|
|
v1: { x: offsetX + medianLineWidth / 2, y: median },
|
|
v2: { x: offsetX - medianLineWidth / 2, y: median }
|
|
};
|
|
const bottomLine = {
|
|
v1: { x: offsetX + whiskerLineWidth / 2, y: whiskerOne },
|
|
v2: { x: offsetX - whiskerLineWidth / 2, y: whiskerOne }
|
|
};
|
|
const verticalLine = {
|
|
v1: { x: offsetX, y: whiskerZero },
|
|
v2: { x: offsetX, y: whiskerOne }
|
|
};
|
|
return [verticalLine, topLine, medianLine, bottomLine];
|
|
}
|
|
updateTooltipSettings() {
|
|
if (this.tooltipDisabled) {
|
|
this.tooltipPlacement = undefined;
|
|
this.tooltipType = undefined;
|
|
}
|
|
else {
|
|
if (!this.tooltipPlacement) {
|
|
this.tooltipPlacement = PlacementTypes.Top;
|
|
}
|
|
if (!this.tooltipType) {
|
|
this.tooltipType = StyleTypes.tooltip;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
BoxSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
BoxSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BoxSeriesComponent, selector: "g[ngx-charts-box-series]", inputs: { dims: "dims", series: "series", xScale: "xScale", yScale: "yScale", colors: "colors", animations: "animations", strokeColor: "strokeColor", strokeWidth: "strokeWidth", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate", tooltipPlacement: "tooltipPlacement", tooltipType: "tooltipType", roundEdges: "roundEdges", gradient: "gradient" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-box
|
|
[@animationState]="'active'"
|
|
[@.disabled]="!animations"
|
|
[width]="box.width"
|
|
[height]="box.height"
|
|
[x]="box.x"
|
|
[y]="box.y"
|
|
[roundEdges]="box.roundEdges"
|
|
[fill]="box.color"
|
|
[gradientStops]="box.gradientStops"
|
|
[strokeColor]="strokeColor"
|
|
[strokeWidth]="strokeWidth"
|
|
[data]="box.data"
|
|
[lineCoordinates]="box.lineCoordinates"
|
|
[gradient]="gradient"
|
|
[ariaLabel]="box.ariaLabel"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTitle"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="box.data"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
`, isInline: true, components: [{ type: BoxComponent, selector: "g[ngx-charts-box]", inputs: ["strokeColor", "strokeWidth", "fill", "data", "width", "height", "x", "y", "lineCoordinates", "roundEdges", "gradient", "gradientStops", "offset", "isActive", "animations", "ariaLabel", "noBarWhenZero"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-box-series]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-box
|
|
[@animationState]="'active'"
|
|
[@.disabled]="!animations"
|
|
[width]="box.width"
|
|
[height]="box.height"
|
|
[x]="box.x"
|
|
[y]="box.y"
|
|
[roundEdges]="box.roundEdges"
|
|
[fill]="box.color"
|
|
[gradientStops]="box.gradientStops"
|
|
[strokeColor]="strokeColor"
|
|
[strokeWidth]="strokeWidth"
|
|
[data]="box.data"
|
|
[lineCoordinates]="box.lineCoordinates"
|
|
[gradient]="gradient"
|
|
[ariaLabel]="box.ariaLabel"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="tooltipPlacement"
|
|
[tooltipType]="tooltipType"
|
|
[tooltipTitle]="tooltipTitle"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="box.data"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({ opacity: 0 }))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], propDecorators: { dims: [{
|
|
type: Input
|
|
}], series: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], strokeColor: [{
|
|
type: Input
|
|
}], strokeWidth: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], tooltipPlacement: [{
|
|
type: Input
|
|
}], tooltipType: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class BoxChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
/** Show or hide the legend. */
|
|
this.legend = false;
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.legendTitle = 'Legend';
|
|
this.showGridLines = true;
|
|
this.xAxis = true;
|
|
this.yAxis = true;
|
|
this.showXAxisLabel = true;
|
|
this.showYAxisLabel = true;
|
|
this.roundDomains = false;
|
|
this.roundEdges = true;
|
|
this.strokeColor = '#FFFFFF';
|
|
this.strokeWidth = 2;
|
|
this.tooltipDisabled = false;
|
|
this.wrapTicks = false;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
/** Chart Margins (For each side, counterclock wise). */
|
|
this.margin = [10, 20, 10, 20];
|
|
/** Chart X axis dimension. */
|
|
this.xAxisHeight = 0;
|
|
/** Chart Y axis dimension. */
|
|
this.yAxisWidth = 0;
|
|
}
|
|
trackBy(index, item) {
|
|
return item.name;
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.xDomain = this.getXDomain();
|
|
this.yDomain = this.getYDomain();
|
|
this.seriesDomain = this.getSeriesDomain();
|
|
this.setScales();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
setColors() {
|
|
let domain = [];
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.seriesDomain;
|
|
}
|
|
else {
|
|
domain = this.yDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
setScales() {
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
|
}
|
|
getXScale(domain, width) {
|
|
const scale = scaleBand()
|
|
.domain(domain.map(d => d.toString()))
|
|
.rangeRound([0, width])
|
|
.padding(0.5);
|
|
return scale;
|
|
}
|
|
getYScale(domain, height) {
|
|
const scale = scaleLinear().domain(domain).range([height, 0]);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getUniqueBoxChartXDomainValues(results) {
|
|
const valueSet = new Set();
|
|
for (const result of results) {
|
|
valueSet.add(result.name);
|
|
}
|
|
return Array.from(valueSet);
|
|
}
|
|
getXDomain() {
|
|
let domain = [];
|
|
const values = this.getUniqueBoxChartXDomainValues(this.results);
|
|
let min;
|
|
let max;
|
|
if (typeof values[0] === 'string') {
|
|
domain = values.map(val => val.toString());
|
|
}
|
|
else if (typeof values[0] === 'number') {
|
|
const mappedValues = values.map(v => Number(v));
|
|
min = Math.min(...mappedValues);
|
|
max = Math.max(...mappedValues);
|
|
domain = [min, max];
|
|
}
|
|
else {
|
|
const mappedValues = values.map(v => Number(new Date(v)));
|
|
min = Math.min(...mappedValues);
|
|
max = Math.max(...mappedValues);
|
|
domain = [new Date(min), new Date(max)];
|
|
}
|
|
return domain;
|
|
}
|
|
getYDomain() {
|
|
const domain = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (domain.indexOf(d.value) < 0) {
|
|
domain.push(d.value);
|
|
}
|
|
}
|
|
}
|
|
const values = [...domain];
|
|
const mappedValues = values.map(v => Number(v));
|
|
const min = Math.min(...mappedValues);
|
|
const max = Math.max(...mappedValues);
|
|
return [min, max];
|
|
}
|
|
getSeriesDomain() {
|
|
return this.results.map(d => `${d.name}`);
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
onActivate(data) {
|
|
this.activate.emit(data);
|
|
}
|
|
onDeactivate(data) {
|
|
this.deactivate.emit(data);
|
|
}
|
|
getLegendOptions() {
|
|
const legendOpts = {
|
|
scaleType: this.schemeType,
|
|
colors: this.colors,
|
|
domain: [],
|
|
position: this.legendPosition,
|
|
title: this.legendTitle
|
|
};
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
legendOpts.domain = this.xDomain;
|
|
legendOpts.colors = this.colors;
|
|
}
|
|
else {
|
|
legendOpts.domain = this.yDomain;
|
|
legendOpts.colors = this.colors.scale;
|
|
}
|
|
return legendOpts;
|
|
}
|
|
}
|
|
BoxChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BoxChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BoxChartComponent, selector: "ngx-charts-box-chart", inputs: { legend: "legend", legendPosition: "legendPosition", legendTitle: "legendTitle", legendOptionsConfig: "legendOptionsConfig", showGridLines: "showGridLines", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", roundDomains: "roundDomains", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", roundEdges: "roundEdges", strokeColor: "strokeColor", strokeWidth: "strokeWidth", tooltipDisabled: "tooltipDisabled", gradient: "gradient", wrapTicks: "wrapTicks" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="box-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
[showGridLines]="showGridLines"
|
|
[dims]="dims"
|
|
[xScale]="xScale"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
[showGridLines]="showGridLines"
|
|
[dims]="dims"
|
|
[yScale]="yScale"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
/>
|
|
</svg:g>
|
|
<svg:g [attr.transform]="transform">
|
|
<svg:g *ngFor="let result of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-box-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[roundEdges]="roundEdges"
|
|
[strokeColor]="strokeColor"
|
|
[strokeWidth]="strokeWidth"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[series]="result"
|
|
[dims]="dims"
|
|
[animations]="animations"
|
|
[gradient]="gradient"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
(select)="onClick($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: BoxSeriesComponent, selector: "g[ngx-charts-box-series]", inputs: ["dims", "series", "xScale", "yScale", "colors", "animations", "strokeColor", "strokeWidth", "tooltipDisabled", "tooltipTemplate", "tooltipPlacement", "tooltipType", "roundEdges", "gradient"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-box-chart', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="box-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
[showGridLines]="showGridLines"
|
|
[dims]="dims"
|
|
[xScale]="xScale"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
[showGridLines]="showGridLines"
|
|
[dims]="dims"
|
|
[yScale]="yScale"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
/>
|
|
</svg:g>
|
|
<svg:g [attr.transform]="transform">
|
|
<svg:g *ngFor="let result of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-box-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[roundEdges]="roundEdges"
|
|
[strokeColor]="strokeColor"
|
|
[strokeWidth]="strokeWidth"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[series]="result"
|
|
[dims]="dims"
|
|
[animations]="animations"
|
|
[gradient]="gradient"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
(select)="onClick($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendOptionsConfig: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], roundEdges: [{
|
|
type: Input
|
|
}], strokeColor: [{
|
|
type: Input
|
|
}], strokeWidth: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate', { static: false }]
|
|
}] } });
|
|
|
|
class BoxChartModule {
|
|
}
|
|
BoxChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
BoxChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxChartModule, declarations: [BoxChartComponent, BoxSeriesComponent, BoxComponent], imports: [ChartCommonModule], exports: [BoxChartComponent, BoxSeriesComponent, BoxComponent] });
|
|
BoxChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxChartModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [BoxChartComponent, BoxSeriesComponent, BoxComponent],
|
|
exports: [BoxChartComponent, BoxSeriesComponent, BoxComponent]
|
|
}]
|
|
}] });
|
|
|
|
function getDomain(values, scaleType, autoScale, minVal, maxVal) {
|
|
let domain = [];
|
|
if (scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
if (!autoScale) {
|
|
values.push(0);
|
|
}
|
|
}
|
|
if (scaleType === ScaleType.Time || scaleType === ScaleType.Linear) {
|
|
const min = minVal || minVal === 0 ? minVal : Math.min(...values);
|
|
const max = maxVal ? maxVal : Math.max(...values);
|
|
domain = [min, max];
|
|
}
|
|
else {
|
|
domain = values;
|
|
}
|
|
return domain;
|
|
}
|
|
function getScale(domain, range, scaleType, roundDomains) {
|
|
switch (scaleType) {
|
|
case ScaleType.Time:
|
|
return scaleTime().range(range).domain(domain);
|
|
case ScaleType.Linear: {
|
|
const scale = scaleLinear().range(range).domain(domain);
|
|
if (roundDomains) {
|
|
return scale.nice();
|
|
}
|
|
return scale;
|
|
}
|
|
case ScaleType.Ordinal:
|
|
return scalePoint()
|
|
.range([range[0], range[1]])
|
|
.domain(domain.map(r => r.toString()));
|
|
default:
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
class BubbleSeriesComponent {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.tooltipDisabled = false;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.circles = this.getCircles();
|
|
}
|
|
getCircles() {
|
|
const seriesName = this.data.name;
|
|
return this.data.series
|
|
.map((d, i) => {
|
|
if (typeof d.y !== 'undefined' && typeof d.x !== 'undefined') {
|
|
const y = d.y;
|
|
const x = d.x;
|
|
const r = d.r;
|
|
const radius = this.rScale(r || 1);
|
|
const tooltipLabel = formatLabel(d.name);
|
|
const cx = this.xScaleType === ScaleType.Linear ? this.xScale(Number(x)) : this.xScale(x);
|
|
const cy = this.yScaleType === ScaleType.Linear ? this.yScale(Number(y)) : this.yScale(y);
|
|
const color = this.colors.scaleType === ScaleType.Linear ? this.colors.getColor(r) : this.colors.getColor(seriesName);
|
|
const isActive = !this.activeEntries.length ? true : this.isActive({ name: seriesName });
|
|
const opacity = isActive ? 1 : 0.3;
|
|
const data = Object.assign({}, d, {
|
|
series: seriesName,
|
|
name: d.name,
|
|
value: d.y,
|
|
x: d.x,
|
|
radius: d.r
|
|
});
|
|
return {
|
|
data,
|
|
x,
|
|
y,
|
|
r,
|
|
classNames: [`circle-data-${i}`],
|
|
value: y,
|
|
label: x,
|
|
cx,
|
|
cy,
|
|
radius,
|
|
tooltipLabel,
|
|
color,
|
|
opacity,
|
|
seriesName,
|
|
isActive,
|
|
transform: `translate(${cx},${cy})`
|
|
};
|
|
}
|
|
})
|
|
.filter(circle => circle !== undefined);
|
|
}
|
|
getTooltipText(circle) {
|
|
const hasRadius = typeof circle.r !== 'undefined';
|
|
const hasTooltipLabel = circle.tooltipLabel && circle.tooltipLabel.length;
|
|
const hasSeriesName = circle.seriesName && circle.seriesName.length;
|
|
const radiusValue = hasRadius ? formatLabel(circle.r) : '';
|
|
const xAxisLabel = this.xAxisLabel && this.xAxisLabel !== '' ? `${this.xAxisLabel}:` : '';
|
|
const yAxisLabel = this.yAxisLabel && this.yAxisLabel !== '' ? `${this.yAxisLabel}:` : '';
|
|
const x = formatLabel(circle.x);
|
|
const y = formatLabel(circle.y);
|
|
const name = hasSeriesName && hasTooltipLabel
|
|
? `${circle.seriesName} • ${circle.tooltipLabel}`
|
|
: circle.seriesName + circle.tooltipLabel;
|
|
const tooltipTitle = hasSeriesName || hasTooltipLabel ? `<span class="tooltip-label">${escapeLabel(name)}</span>` : '';
|
|
return `
|
|
${tooltipTitle}
|
|
<span class="tooltip-label">
|
|
<label>${escapeLabel(xAxisLabel)}</label> ${escapeLabel(x)}<br />
|
|
<label>${escapeLabel(yAxisLabel)}</label> ${escapeLabel(y)}
|
|
</span>
|
|
<span class="tooltip-val">
|
|
${escapeLabel(radiusValue)}
|
|
</span>
|
|
`;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
isVisible(circle) {
|
|
if (this.activeEntries.length > 0) {
|
|
return this.isActive({ name: circle.seriesName });
|
|
}
|
|
return circle.opacity !== 0;
|
|
}
|
|
activateCircle(circle) {
|
|
circle.barVisible = true;
|
|
this.activate.emit({ name: this.data.name });
|
|
}
|
|
deactivateCircle(circle) {
|
|
circle.barVisible = false;
|
|
this.deactivate.emit({ name: this.data.name });
|
|
}
|
|
trackBy(index, circle) {
|
|
return `${circle.data.series} ${circle.data.name}`;
|
|
}
|
|
}
|
|
BubbleSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleSeriesComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
BubbleSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BubbleSeriesComponent, selector: "g[ngx-charts-bubble-series]", inputs: { data: "data", xScale: "xScale", yScale: "yScale", rScale: "rScale", xScaleType: "xScaleType", yScaleType: "yScaleType", colors: "colors", visibleValue: "visibleValue", activeEntries: "activeEntries", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g *ngFor="let circle of circles; trackBy: trackBy">
|
|
<svg:g [attr.transform]="circle.transform">
|
|
<svg:g
|
|
*ngIf="!isSSR"
|
|
ngx-charts-circle
|
|
[@animationState]="'active'"
|
|
class="circle"
|
|
[cx]="0"
|
|
[cy]="0"
|
|
[r]="circle.radius"
|
|
[fill]="circle.color"
|
|
[style.opacity]="circle.opacity"
|
|
[class.active]="circle.isActive"
|
|
[pointerEvents]="'all'"
|
|
[data]="circle.value"
|
|
[classNames]="circle.classNames"
|
|
(select)="onClick(circle.data)"
|
|
(activate)="activateCircle(circle)"
|
|
(deactivate)="deactivateCircle(circle)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
/>
|
|
<svg:g
|
|
*ngIf="isSSR"
|
|
ngx-charts-circle
|
|
class="circle"
|
|
[cx]="0"
|
|
[cy]="0"
|
|
[r]="circle.radius"
|
|
[fill]="circle.color"
|
|
[style.opacity]="circle.opacity"
|
|
[class.active]="circle.isActive"
|
|
[pointerEvents]="'all'"
|
|
[data]="circle.value"
|
|
[classNames]="circle.classNames"
|
|
(select)="onClick(circle.data)"
|
|
(activate)="activateCircle(circle)"
|
|
(deactivate)="deactivateCircle(circle)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: CircleComponent, selector: "g[ngx-charts-circle]", inputs: ["cx", "cy", "r", "fill", "stroke", "data", "classNames", "circleOpacity", "pointerEvents"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':enter', [
|
|
style({
|
|
opacity: 0,
|
|
transform: 'scale(0)'
|
|
}),
|
|
animate(250, style({ opacity: 1, transform: 'scale(1)' }))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-bubble-series]',
|
|
template: `
|
|
<svg:g *ngFor="let circle of circles; trackBy: trackBy">
|
|
<svg:g [attr.transform]="circle.transform">
|
|
<svg:g
|
|
*ngIf="!isSSR"
|
|
ngx-charts-circle
|
|
[@animationState]="'active'"
|
|
class="circle"
|
|
[cx]="0"
|
|
[cy]="0"
|
|
[r]="circle.radius"
|
|
[fill]="circle.color"
|
|
[style.opacity]="circle.opacity"
|
|
[class.active]="circle.isActive"
|
|
[pointerEvents]="'all'"
|
|
[data]="circle.value"
|
|
[classNames]="circle.classNames"
|
|
(select)="onClick(circle.data)"
|
|
(activate)="activateCircle(circle)"
|
|
(deactivate)="deactivateCircle(circle)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
/>
|
|
<svg:g
|
|
*ngIf="isSSR"
|
|
ngx-charts-circle
|
|
class="circle"
|
|
[cx]="0"
|
|
[cy]="0"
|
|
[r]="circle.radius"
|
|
[fill]="circle.color"
|
|
[style.opacity]="circle.opacity"
|
|
[class.active]="circle.isActive"
|
|
[pointerEvents]="'all'"
|
|
[data]="circle.value"
|
|
[classNames]="circle.classNames"
|
|
(select)="onClick(circle.data)"
|
|
(activate)="activateCircle(circle)"
|
|
(deactivate)="deactivateCircle(circle)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition(':enter', [
|
|
style({
|
|
opacity: 0,
|
|
transform: 'scale(0)'
|
|
}),
|
|
animate(250, style({ opacity: 1, transform: 'scale(1)' }))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { data: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], rScale: [{
|
|
type: Input
|
|
}], xScaleType: [{
|
|
type: Input
|
|
}], yScaleType: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], visibleValue: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class BubbleChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.showGridLines = true;
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.xAxis = true;
|
|
this.yAxis = true;
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.roundDomains = false;
|
|
this.maxRadius = 10;
|
|
this.minRadius = 3;
|
|
this.schemeType = ScaleType.Ordinal;
|
|
this.tooltipDisabled = false;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.scaleType = ScaleType.Linear;
|
|
this.margin = [10, 20, 10, 20];
|
|
this.bubblePadding = [0, 0, 0, 0];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.activeEntries = [];
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.seriesDomain = this.results.map(d => d.name);
|
|
this.rDomain = this.getRDomain();
|
|
this.xDomain = this.getXDomain();
|
|
this.yDomain = this.getYDomain();
|
|
this.transform = `translate(${this.dims.xOffset},${this.margin[0]})`;
|
|
const colorDomain = this.schemeType === ScaleType.Ordinal ? this.seriesDomain : this.rDomain;
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, colorDomain, this.customColors);
|
|
this.data = this.results;
|
|
this.minRadius = Math.max(this.minRadius, 1);
|
|
this.maxRadius = Math.max(this.maxRadius, 1);
|
|
this.rScale = this.getRScale(this.rDomain, [this.minRadius, this.maxRadius]);
|
|
this.bubblePadding = [0, 0, 0, 0];
|
|
this.setScales();
|
|
this.bubblePadding = this.getBubblePadding();
|
|
this.setScales();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.clipPathId = 'clip' + id().toString();
|
|
this.clipPath = `url(#${this.clipPathId})`;
|
|
}
|
|
hideCircles() {
|
|
this.deactivateAll();
|
|
}
|
|
onClick(data, series) {
|
|
if (series) {
|
|
data.series = series.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
getBubblePadding() {
|
|
let yMin = 0;
|
|
let xMin = 0;
|
|
let yMax = this.dims.height;
|
|
let xMax = this.dims.width;
|
|
for (const s of this.data) {
|
|
for (const d of s.series) {
|
|
const r = this.rScale(d.r);
|
|
const cx = this.xScaleType === ScaleType.Linear ? this.xScale(Number(d.x)) : this.xScale(d.x);
|
|
const cy = this.yScaleType === ScaleType.Linear ? this.yScale(Number(d.y)) : this.yScale(d.y);
|
|
xMin = Math.max(r - cx, xMin);
|
|
yMin = Math.max(r - cy, yMin);
|
|
yMax = Math.max(cy + r, yMax);
|
|
xMax = Math.max(cx + r, xMax);
|
|
}
|
|
}
|
|
xMax = Math.max(xMax - this.dims.width, 0);
|
|
yMax = Math.max(yMax - this.dims.height, 0);
|
|
return [yMin, xMax, yMax, xMin];
|
|
}
|
|
setScales() {
|
|
let width = this.dims.width;
|
|
if (this.xScaleMin === undefined && this.xScaleMax === undefined) {
|
|
width = width - this.bubblePadding[1];
|
|
}
|
|
let height = this.dims.height;
|
|
if (this.yScaleMin === undefined && this.yScaleMax === undefined) {
|
|
height = height - this.bubblePadding[2];
|
|
}
|
|
this.xScale = this.getXScale(this.xDomain, width);
|
|
this.yScale = this.getYScale(this.yDomain, height);
|
|
}
|
|
getYScale(domain, height) {
|
|
return getScale(domain, [height, this.bubblePadding[0]], this.yScaleType, this.roundDomains);
|
|
}
|
|
getXScale(domain, width) {
|
|
return getScale(domain, [this.bubblePadding[3], width], this.xScaleType, this.roundDomains);
|
|
}
|
|
getRScale(domain, range) {
|
|
const scale = scaleLinear().range(range).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
position: this.legendPosition,
|
|
title: undefined
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.seriesDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.rDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
getXDomain() {
|
|
const values = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (!values.includes(d.x)) {
|
|
values.push(d.x);
|
|
}
|
|
}
|
|
}
|
|
this.xScaleType = getScaleType(values);
|
|
return getDomain(values, this.xScaleType, this.autoScale, this.xScaleMin, this.xScaleMax);
|
|
}
|
|
getYDomain() {
|
|
const values = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (!values.includes(d.y)) {
|
|
values.push(d.y);
|
|
}
|
|
}
|
|
}
|
|
this.yScaleType = getScaleType(values);
|
|
return getDomain(values, this.yScaleType, this.autoScale, this.yScaleMin, this.yScaleMax);
|
|
}
|
|
getRDomain() {
|
|
let min = Infinity;
|
|
let max = -Infinity;
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
const value = Number(d.r) || 1;
|
|
min = Math.min(min, value);
|
|
max = Math.max(max, value);
|
|
}
|
|
}
|
|
return [min, max];
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
deactivateAll() {
|
|
this.activeEntries = [...this.activeEntries];
|
|
for (const entry of this.activeEntries) {
|
|
this.deactivate.emit({ value: entry, entries: [] });
|
|
}
|
|
this.activeEntries = [];
|
|
}
|
|
trackBy(index, item) {
|
|
return `${item.name}`;
|
|
}
|
|
}
|
|
BubbleChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
BubbleChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BubbleChartComponent, selector: "ngx-charts-bubble-chart", inputs: { showGridLines: "showGridLines", legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", roundDomains: "roundDomains", maxRadius: "maxRadius", minRadius: "minRadius", autoScale: "autoScale", schemeType: "schemeType", tooltipDisabled: "tooltipDisabled", xScaleMin: "xScaleMin", xScaleMax: "xScaleMax", yScaleMin: "yScaleMin", yScaleMax: "yScaleMax", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseleave": "hideCircles()" } }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[activeEntries]="activeEntries"
|
|
[legendOptions]="legendOptions"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="bubble-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[showGridLines]="showGridLines"
|
|
[dims]="dims"
|
|
[xScale]="xScale"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[showGridLines]="showGridLines"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
/>
|
|
<svg:rect
|
|
class="bubble-chart-area"
|
|
x="0"
|
|
y="0"
|
|
[attr.width]="dims.width"
|
|
[attr.height]="dims.height"
|
|
style="fill: rgb(255, 0, 0); opacity: 0; cursor: 'auto';"
|
|
(mouseenter)="deactivateAll()"
|
|
/>
|
|
<svg:g *ngIf="!isSSR" [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of data; trackBy: trackBy" [@animationState]="'active'">
|
|
<svg:g
|
|
ngx-charts-bubble-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[rScale]="rScale"
|
|
[xScaleType]="xScaleType"
|
|
[yScaleType]="yScaleType"
|
|
[xAxisLabel]="xAxisLabel"
|
|
[yAxisLabel]="yAxisLabel"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR" [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of data; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-bubble-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[rScale]="rScale"
|
|
[xScaleType]="xScaleType"
|
|
[yScaleType]="yScaleType"
|
|
[xAxisLabel]="xAxisLabel"
|
|
[yAxisLabel]="yAxisLabel"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: BubbleSeriesComponent, selector: "g[ngx-charts-bubble-series]", inputs: ["data", "xScale", "yScale", "rScale", "xScaleType", "yScaleType", "colors", "visibleValue", "activeEntries", "xAxisLabel", "yAxisLabel", "tooltipDisabled", "tooltipTemplate"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({
|
|
opacity: 0
|
|
}))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-bubble-chart', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[activeEntries]="activeEntries"
|
|
[legendOptions]="legendOptions"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="bubble-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[showGridLines]="showGridLines"
|
|
[dims]="dims"
|
|
[xScale]="xScale"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[showGridLines]="showGridLines"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
/>
|
|
<svg:rect
|
|
class="bubble-chart-area"
|
|
x="0"
|
|
y="0"
|
|
[attr.width]="dims.width"
|
|
[attr.height]="dims.height"
|
|
style="fill: rgb(255, 0, 0); opacity: 0; cursor: 'auto';"
|
|
(mouseenter)="deactivateAll()"
|
|
/>
|
|
<svg:g *ngIf="!isSSR" [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of data; trackBy: trackBy" [@animationState]="'active'">
|
|
<svg:g
|
|
ngx-charts-bubble-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[rScale]="rScale"
|
|
[xScaleType]="xScaleType"
|
|
[yScaleType]="yScaleType"
|
|
[xAxisLabel]="xAxisLabel"
|
|
[yAxisLabel]="yAxisLabel"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR" [attr.clip-path]="clipPath">
|
|
<svg:g *ngFor="let series of data; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-bubble-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[rScale]="rScale"
|
|
[xScaleType]="xScaleType"
|
|
[yScaleType]="yScaleType"
|
|
[xAxisLabel]="xAxisLabel"
|
|
[yAxisLabel]="yAxisLabel"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event, series)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({
|
|
opacity: 0
|
|
}))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { showGridLines: [{
|
|
type: Input
|
|
}], legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], maxRadius: [{
|
|
type: Input
|
|
}], minRadius: [{
|
|
type: Input
|
|
}], autoScale: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], xScaleMin: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], yScaleMin: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], hideCircles: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class BubbleChartModule {
|
|
}
|
|
BubbleChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
BubbleChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleChartModule, declarations: [BubbleChartComponent, BubbleSeriesComponent], imports: [ChartCommonModule], exports: [BubbleChartComponent, BubbleSeriesComponent] });
|
|
BubbleChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleChartModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BubbleChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [BubbleChartComponent, BubbleSeriesComponent],
|
|
exports: [BubbleChartComponent, BubbleSeriesComponent]
|
|
}]
|
|
}] });
|
|
|
|
class HeatMapCellComponent {
|
|
constructor(element) {
|
|
this.gradient = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.barOrientation = BarOrientation;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.transform = `translate(${this.x} , ${this.y})`;
|
|
this.startOpacity = 0.3;
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientUrl = `url(#${this.gradientId})`;
|
|
this.gradientStops = this.getGradientStops();
|
|
if (this.animations) {
|
|
this.loadAnimation();
|
|
}
|
|
}
|
|
getGradientStops() {
|
|
return [
|
|
{
|
|
offset: 0,
|
|
color: this.fill,
|
|
opacity: this.startOpacity
|
|
},
|
|
{
|
|
offset: 100,
|
|
color: this.fill,
|
|
opacity: 1
|
|
}
|
|
];
|
|
}
|
|
loadAnimation() {
|
|
const node = select(this.element).select('.cell');
|
|
node.attr('opacity', 0);
|
|
this.animateToCurrentForm();
|
|
}
|
|
animateToCurrentForm() {
|
|
const node = select(this.element).select('.cell');
|
|
node.transition().duration(750).attr('opacity', 1);
|
|
}
|
|
onClick() {
|
|
this.select.emit(this.data);
|
|
}
|
|
onMouseEnter() {
|
|
this.activate.emit(this.data);
|
|
}
|
|
onMouseLeave() {
|
|
this.deactivate.emit(this.data);
|
|
}
|
|
}
|
|
HeatMapCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapCellComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
HeatMapCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: HeatMapCellComponent, selector: "g[ngx-charts-heat-map-cell]", inputs: { fill: "fill", x: "x", y: "y", width: "width", height: "height", data: "data", gradient: "gradient", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g [attr.transform]="transform" class="cell">
|
|
<defs *ngIf="gradient">
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:rect
|
|
[attr.fill]="gradient ? gradientUrl : fill"
|
|
rx="3"
|
|
[attr.width]="width"
|
|
[attr.height]="height"
|
|
class="cell"
|
|
(click)="onClick()"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapCellComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-heat-map-cell]',
|
|
template: `
|
|
<svg:g [attr.transform]="transform" class="cell">
|
|
<defs *ngIf="gradient">
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:rect
|
|
[attr.fill]="gradient ? gradientUrl : fill"
|
|
rx="3"
|
|
[attr.width]="width"
|
|
[attr.height]="height"
|
|
class="cell"
|
|
(click)="onClick()"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { fill: [{
|
|
type: Input
|
|
}], x: [{
|
|
type: Input
|
|
}], y: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], onMouseEnter: [{
|
|
type: HostListener,
|
|
args: ['mouseenter']
|
|
}], onMouseLeave: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class HeatCellSeriesComponent {
|
|
constructor() {
|
|
this.tooltipDisabled = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
}
|
|
ngOnInit() {
|
|
if (!this.tooltipText) {
|
|
this.tooltipText = this.getTooltipText;
|
|
}
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.cells = this.getCells();
|
|
}
|
|
getCells() {
|
|
const cells = [];
|
|
this.data.map(row => {
|
|
row.series.map(cell => {
|
|
const value = cell.value;
|
|
cell.series = row.name;
|
|
cells.push({
|
|
row,
|
|
cell,
|
|
x: this.xScale(row.name),
|
|
y: this.yScale(cell.name),
|
|
width: this.xScale.bandwidth(),
|
|
height: this.yScale.bandwidth(),
|
|
fill: this.colors.getColor(value),
|
|
data: value,
|
|
label: formatLabel(cell.name),
|
|
series: row.name
|
|
});
|
|
});
|
|
});
|
|
return cells;
|
|
}
|
|
getTooltipText({ label, data, series }) {
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(series)} • ${escapeLabel(label)}</span>
|
|
<span class="tooltip-val">${data.toLocaleString()}</span>
|
|
`;
|
|
}
|
|
trackBy(index, item) {
|
|
return item.label;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
}
|
|
HeatCellSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatCellSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
HeatCellSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: HeatCellSeriesComponent, selector: "g[ngx-charts-heat-map-cell-series]", inputs: { data: "data", colors: "colors", xScale: "xScale", yScale: "yScale", gradient: "gradient", tooltipDisabled: "tooltipDisabled", tooltipText: "tooltipText", tooltipTemplate: "tooltipTemplate", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-heat-map-cell
|
|
*ngFor="let c of cells; trackBy: trackBy"
|
|
[x]="c.x"
|
|
[y]="c.y"
|
|
[width]="c.width"
|
|
[height]="c.height"
|
|
[fill]="c.fill"
|
|
[data]="c.data"
|
|
(select)="onClick(c.cell)"
|
|
(activate)="activate.emit(c.cell)"
|
|
(deactivate)="deactivate.emit(c.cell)"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText(c)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="{ series: c.series, name: c.label, value: c.data }"
|
|
></svg:g>
|
|
`, isInline: true, components: [{ type: HeatMapCellComponent, selector: "g[ngx-charts-heat-map-cell]", inputs: ["fill", "x", "y", "width", "height", "data", "gradient", "animations"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatCellSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-heat-map-cell-series]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-heat-map-cell
|
|
*ngFor="let c of cells; trackBy: trackBy"
|
|
[x]="c.x"
|
|
[y]="c.y"
|
|
[width]="c.width"
|
|
[height]="c.height"
|
|
[fill]="c.fill"
|
|
[data]="c.data"
|
|
(select)="onClick(c.cell)"
|
|
(activate)="activate.emit(c.cell)"
|
|
(deactivate)="deactivate.emit(c.cell)"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText(c)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="{ series: c.series, name: c.label, value: c.data }"
|
|
></svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { data: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class HeatMapComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.innerPadding = 8;
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.tooltipDisabled = false;
|
|
this.activeEntries = [];
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.scaleType = ScaleType.Linear;
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.formatDates();
|
|
this.xDomain = this.getXDomain();
|
|
this.yDomain = this.getYDomain();
|
|
this.valueDomain = this.getValueDomain();
|
|
this.scaleType = getScaleType(this.valueDomain, false);
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.scaleType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
let min = this.min;
|
|
let max = this.max;
|
|
if (!this.min) {
|
|
min = Math.min(0, ...this.valueDomain);
|
|
}
|
|
if (!this.max) {
|
|
max = Math.max(...this.valueDomain);
|
|
}
|
|
this.valueDomain = [min, max];
|
|
}
|
|
this.xScale = this.getXScale();
|
|
this.yScale = this.getYScale();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
this.rects = this.getRects();
|
|
}
|
|
getXDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
if (!domain.includes(group.name)) {
|
|
domain.push(group.name);
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getYDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.name)) {
|
|
domain.push(d.name);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getValueDomain() {
|
|
const domain = [];
|
|
for (const group of this.results) {
|
|
for (const d of group.series) {
|
|
if (!domain.includes(d.value)) {
|
|
domain.push(d.value);
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
/**
|
|
* Converts the input to gap paddingInner in fraction
|
|
* Supports the following inputs:
|
|
* Numbers: 8
|
|
* Strings: "8", "8px", "8%"
|
|
* Arrays: [8,2], "8,2", "[8,2]"
|
|
* Mixed: [8,"2%"], ["8px","2%"], "8,2%", "[8,2%]"
|
|
*
|
|
* @memberOf HeatMapComponent
|
|
*/
|
|
getDimension(value, index = 0, N, L) {
|
|
if (typeof value === 'string') {
|
|
value = value
|
|
.replace('[', '')
|
|
.replace(']', '')
|
|
.replace('px', '')
|
|
// tslint:disable-next-line: quotemark
|
|
.replace("'", '');
|
|
if (value.includes(',')) {
|
|
value = value.split(',');
|
|
}
|
|
}
|
|
if (Array.isArray(value) && typeof index === 'number') {
|
|
return this.getDimension(value[index], null, N, L);
|
|
}
|
|
if (typeof value === 'string' && value.includes('%')) {
|
|
return +value.replace('%', '') / 100;
|
|
}
|
|
return N / (L / +value + 1);
|
|
}
|
|
getXScale() {
|
|
const f = this.getDimension(this.innerPadding, 0, this.xDomain.length, this.dims.width);
|
|
return scaleBand().rangeRound([0, this.dims.width]).domain(this.xDomain).paddingInner(f);
|
|
}
|
|
getYScale() {
|
|
const f = this.getDimension(this.innerPadding, 1, this.yDomain.length, this.dims.height);
|
|
return scaleBand().rangeRound([this.dims.height, 0]).domain(this.yDomain).paddingInner(f);
|
|
}
|
|
getRects() {
|
|
const rects = [];
|
|
this.xDomain.map(xVal => {
|
|
this.yDomain.map(yVal => {
|
|
rects.push({
|
|
x: this.xScale(xVal),
|
|
y: this.yScale(yVal),
|
|
rx: 3,
|
|
width: this.xScale.bandwidth(),
|
|
height: this.yScale.bandwidth(),
|
|
fill: 'rgba(200,200,200,0.03)'
|
|
});
|
|
});
|
|
});
|
|
return rects;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, this.scaleType, this.valueDomain);
|
|
}
|
|
getLegendOptions() {
|
|
return {
|
|
scaleType: this.scaleType,
|
|
domain: this.valueDomain,
|
|
colors: this.scaleType === ScaleType.Ordinal ? this.colors : this.colors.scale,
|
|
title: this.scaleType === ScaleType.Ordinal ? this.legendTitle : undefined,
|
|
position: this.legendPosition
|
|
};
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
const items = this.results
|
|
.map(g => g.series)
|
|
.flat()
|
|
.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label === item.name;
|
|
}
|
|
else {
|
|
return i.name === item.name && i.series === item.series;
|
|
}
|
|
});
|
|
this.activeEntries = [...items];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(event, group, fromLegend = false) {
|
|
const item = Object.assign({}, event);
|
|
if (group) {
|
|
item.series = group.name;
|
|
}
|
|
this.activeEntries = this.activeEntries.filter(i => {
|
|
if (fromLegend) {
|
|
return i.label !== item.name;
|
|
}
|
|
else {
|
|
return !(i.name === item.name && i.series === item.series);
|
|
}
|
|
});
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
HeatMapComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
HeatMapComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: HeatMapComponent, selector: "ngx-charts-heat-map", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", gradient: "gradient", innerPadding: "innerPadding", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", tooltipDisabled: "tooltipDisabled", tooltipText: "tooltipText", min: "min", max: "max", activeEntries: "activeEntries", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[animations]="animations"
|
|
[legendOptions]="legendOptions"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="heat-map chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:rect
|
|
*ngFor="let rect of rects"
|
|
[attr.x]="rect.x"
|
|
[attr.y]="rect.y"
|
|
[attr.rx]="rect.rx"
|
|
[attr.width]="rect.width"
|
|
[attr.height]="rect.height"
|
|
[attr.fill]="rect.fill"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-heat-map-cell-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="results"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipText]="tooltipText"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event, undefined)"
|
|
(deactivate)="onDeactivate($event, undefined)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: HeatCellSeriesComponent, selector: "g[ngx-charts-heat-map-cell-series]", inputs: ["data", "colors", "xScale", "yScale", "gradient", "tooltipDisabled", "tooltipText", "tooltipTemplate", "animations"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-heat-map', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[animations]="animations"
|
|
[legendOptions]="legendOptions"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="heat-map chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:rect
|
|
*ngFor="let rect of rects"
|
|
[attr.x]="rect.x"
|
|
[attr.y]="rect.y"
|
|
[attr.rx]="rect.rx"
|
|
[attr.width]="rect.width"
|
|
[attr.height]="rect.height"
|
|
[attr.fill]="rect.fill"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-heat-map-cell-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="results"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipText]="tooltipText"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event, undefined)"
|
|
(deactivate)="onDeactivate($event, undefined)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], innerPadding: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], min: [{
|
|
type: Input
|
|
}], max: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class HeatMapModule {
|
|
}
|
|
HeatMapModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
HeatMapModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapModule, declarations: [HeatMapCellComponent, HeatCellSeriesComponent, HeatMapComponent], imports: [ChartCommonModule], exports: [HeatMapCellComponent, HeatCellSeriesComponent, HeatMapComponent] });
|
|
HeatMapModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: HeatMapModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [HeatMapCellComponent, HeatCellSeriesComponent, HeatMapComponent],
|
|
exports: [HeatMapCellComponent, HeatCellSeriesComponent, HeatMapComponent]
|
|
}]
|
|
}] });
|
|
|
|
class LineComponent {
|
|
constructor(element, platformId) {
|
|
this.element = element;
|
|
this.platformId = platformId;
|
|
this.fill = 'none';
|
|
this.animations = true;
|
|
// @Output() select = new EventEmitter();
|
|
this.initialized = false;
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
ngOnChanges(changes) {
|
|
if (!this.initialized) {
|
|
this.initialized = true;
|
|
this.initialPath = this.path;
|
|
}
|
|
else {
|
|
this.updatePathEl();
|
|
}
|
|
}
|
|
updatePathEl() {
|
|
const node = select(this.element.nativeElement).select('.line');
|
|
if (this.animations) {
|
|
node.transition().duration(750).attr('d', this.path);
|
|
}
|
|
else {
|
|
node.attr('d', this.path);
|
|
}
|
|
}
|
|
}
|
|
LineComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineComponent, deps: [{ token: i0.ElementRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
LineComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LineComponent, selector: "g[ngx-charts-line]", inputs: { path: "path", stroke: "stroke", data: "data", fill: "fill", animations: "animations" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:path
|
|
[@animationState]="'active'"
|
|
class="line"
|
|
[attr.d]="initialPath"
|
|
[attr.fill]="fill"
|
|
[attr.stroke]="stroke"
|
|
stroke-width="1.5px"
|
|
/>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:path class="line" [attr.d]="initialPath" [attr.fill]="fill" [attr.stroke]="stroke" stroke-width="1.5px" />
|
|
</svg:g>
|
|
`, isInline: true, directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':enter', [
|
|
style({
|
|
strokeDasharray: 2000,
|
|
strokeDashoffset: 2000
|
|
}),
|
|
animate(1000, style({
|
|
strokeDashoffset: 0
|
|
}))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-line]',
|
|
template: `
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:path
|
|
[@animationState]="'active'"
|
|
class="line"
|
|
[attr.d]="initialPath"
|
|
[attr.fill]="fill"
|
|
[attr.stroke]="stroke"
|
|
stroke-width="1.5px"
|
|
/>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:path class="line" [attr.d]="initialPath" [attr.fill]="fill" [attr.stroke]="stroke" stroke-width="1.5px" />
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
animations: [
|
|
trigger('animationState', [
|
|
transition(':enter', [
|
|
style({
|
|
strokeDasharray: 2000,
|
|
strokeDashoffset: 2000
|
|
}),
|
|
animate(1000, style({
|
|
strokeDashoffset: 0
|
|
}))
|
|
])
|
|
])
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { path: [{
|
|
type: Input
|
|
}], stroke: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], fill: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class LineSeriesComponent {
|
|
constructor() {
|
|
this.animations = true;
|
|
this.barOrientation = BarOrientation;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.updateGradients();
|
|
const data = this.sortData(this.data.series);
|
|
const lineGen = this.getLineGenerator();
|
|
this.path = lineGen(data) || '';
|
|
const areaGen = this.getAreaGenerator();
|
|
this.areaPath = areaGen(data) || '';
|
|
if (this.hasRange) {
|
|
const range = this.getRangeGenerator();
|
|
this.outerPath = range(data) || '';
|
|
}
|
|
if (this.hasGradient) {
|
|
this.stroke = this.gradientUrl;
|
|
const values = this.data.series.map(d => d.value);
|
|
const max = Math.max(...values);
|
|
const min = Math.min(...values);
|
|
if (max === min) {
|
|
this.stroke = this.colors.getColor(max);
|
|
}
|
|
}
|
|
else {
|
|
this.stroke = this.colors.getColor(this.data.name);
|
|
}
|
|
}
|
|
getLineGenerator() {
|
|
return line()
|
|
.x(d => {
|
|
const label = d.name;
|
|
let value;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
value = this.xScale(label);
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
value = this.xScale(Number(label));
|
|
}
|
|
else {
|
|
value = this.xScale(label);
|
|
}
|
|
return value;
|
|
})
|
|
.y(d => this.yScale(d.value))
|
|
.curve(this.curve);
|
|
}
|
|
getRangeGenerator() {
|
|
return area()
|
|
.x(d => {
|
|
const label = d.name;
|
|
let value;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
value = this.xScale(label);
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
value = this.xScale(Number(label));
|
|
}
|
|
else {
|
|
value = this.xScale(label);
|
|
}
|
|
return value;
|
|
})
|
|
.y0(d => this.yScale(typeof d.min === 'number' ? d.min : d.value))
|
|
.y1(d => this.yScale(typeof d.max === 'number' ? d.max : d.value))
|
|
.curve(this.curve);
|
|
}
|
|
getAreaGenerator() {
|
|
const xProperty = d => {
|
|
const label = d.name;
|
|
return this.xScale(label);
|
|
};
|
|
return area()
|
|
.x(xProperty)
|
|
.y0(() => this.yScale.range()[0])
|
|
.y1(d => this.yScale(d.value))
|
|
.curve(this.curve);
|
|
}
|
|
sortData(data) {
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
data = sortLinear(data, 'name');
|
|
}
|
|
else if (this.scaleType === ScaleType.Time) {
|
|
data = sortByTime(data, 'name');
|
|
}
|
|
else {
|
|
data = sortByDomain(data, 'name', 'asc', this.xScale.domain());
|
|
}
|
|
return data;
|
|
}
|
|
updateGradients() {
|
|
if (this.colors.scaleType === ScaleType.Linear) {
|
|
this.hasGradient = true;
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientUrl = `url(#${this.gradientId})`;
|
|
const values = this.data.series.map(d => d.value);
|
|
const max = Math.max(...values);
|
|
const min = Math.min(...values);
|
|
this.gradientStops = this.colors.getLinearGradientStops(max, min);
|
|
this.areaGradientStops = this.colors.getLinearGradientStops(max);
|
|
}
|
|
else {
|
|
this.hasGradient = false;
|
|
this.gradientStops = undefined;
|
|
this.areaGradientStops = undefined;
|
|
}
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
isInactive(entry) {
|
|
if (!this.activeEntries || this.activeEntries.length === 0)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item === undefined;
|
|
}
|
|
}
|
|
LineSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
LineSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LineSeriesComponent, selector: "g[ngx-charts-line-series]", inputs: { data: "data", xScale: "xScale", yScale: "yScale", colors: "colors", scaleType: "scaleType", curve: "curve", activeEntries: "activeEntries", rangeFillOpacity: "rangeFillOpacity", hasRange: "hasRange", animations: "animations" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g>
|
|
<defs>
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
*ngIf="hasGradient"
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:g
|
|
ngx-charts-area
|
|
class="line-highlight"
|
|
[data]="data"
|
|
[path]="areaPath"
|
|
[fill]="hasGradient ? gradientUrl : colors.getColor(data.name)"
|
|
[opacity]="0.25"
|
|
[startOpacity]="0"
|
|
[gradient]="true"
|
|
[stops]="areaGradientStops"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
[animations]="animations"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-line
|
|
class="line-series"
|
|
[data]="data"
|
|
[path]="path"
|
|
[stroke]="stroke"
|
|
[animations]="animations"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-area
|
|
*ngIf="hasRange"
|
|
class="line-series-range"
|
|
[data]="data"
|
|
[path]="outerPath"
|
|
[fill]="hasGradient ? gradientUrl : colors.getColor(data.name)"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
[opacity]="rangeFillOpacity"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }, { type: AreaComponent, selector: "g[ngx-charts-area]", inputs: ["data", "path", "startingPath", "fill", "opacity", "startOpacity", "endOpacity", "gradient", "stops", "animations"], outputs: ["select"] }, { type: LineComponent, selector: "g[ngx-charts-line]", inputs: ["path", "stroke", "data", "fill", "animations"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-line-series]',
|
|
template: `
|
|
<svg:g>
|
|
<defs>
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
*ngIf="hasGradient"
|
|
[orientation]="barOrientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:g
|
|
ngx-charts-area
|
|
class="line-highlight"
|
|
[data]="data"
|
|
[path]="areaPath"
|
|
[fill]="hasGradient ? gradientUrl : colors.getColor(data.name)"
|
|
[opacity]="0.25"
|
|
[startOpacity]="0"
|
|
[gradient]="true"
|
|
[stops]="areaGradientStops"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
[animations]="animations"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-line
|
|
class="line-series"
|
|
[data]="data"
|
|
[path]="path"
|
|
[stroke]="stroke"
|
|
[animations]="animations"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-area
|
|
*ngIf="hasRange"
|
|
class="line-series-range"
|
|
[data]="data"
|
|
[path]="outerPath"
|
|
[fill]="hasGradient ? gradientUrl : colors.getColor(data.name)"
|
|
[class.active]="isActive(data)"
|
|
[class.inactive]="isInactive(data)"
|
|
[opacity]="rangeFillOpacity"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { data: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], scaleType: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], rangeFillOpacity: [{
|
|
type: Input
|
|
}], hasRange: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class LineChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.showGridLines = true;
|
|
this.curve = curveLinear;
|
|
this.activeEntries = [];
|
|
this.trimXAxisTicks = true;
|
|
this.trimYAxisTicks = true;
|
|
this.rotateXAxisTicks = true;
|
|
this.maxXAxisTickLength = 16;
|
|
this.maxYAxisTickLength = 16;
|
|
this.roundDomains = false;
|
|
this.tooltipDisabled = false;
|
|
this.showRefLines = false;
|
|
this.showRefLabels = true;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.timelineHeight = 50;
|
|
this.timelinePadding = 10;
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
if (this.timeline) {
|
|
this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
|
}
|
|
this.xDomain = this.getXDomain();
|
|
if (this.filteredDomain) {
|
|
this.xDomain = this.filteredDomain;
|
|
}
|
|
this.yDomain = this.getYDomain();
|
|
this.seriesDomain = this.getSeriesDomain();
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
|
this.updateTimeline();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
this.clipPathId = 'clip' + id().toString();
|
|
this.clipPath = `url(#${this.clipPathId})`;
|
|
}
|
|
updateTimeline() {
|
|
if (this.timeline) {
|
|
this.timelineWidth = this.dims.width;
|
|
this.timelineXDomain = this.getXDomain();
|
|
this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
|
this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
|
this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
|
}
|
|
}
|
|
getXDomain() {
|
|
let values = getUniqueXDomainValues(this.results);
|
|
this.scaleType = getScaleType(values);
|
|
let domain = [];
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
}
|
|
let min;
|
|
let max;
|
|
if (this.scaleType === ScaleType.Time || this.scaleType === ScaleType.Linear) {
|
|
min = this.xScaleMin ? this.xScaleMin : Math.min(...values);
|
|
max = this.xScaleMax ? this.xScaleMax : Math.max(...values);
|
|
}
|
|
if (this.scaleType === ScaleType.Time) {
|
|
domain = [new Date(min), new Date(max)];
|
|
this.xSet = [...values].sort((a, b) => {
|
|
const aDate = a.getTime();
|
|
const bDate = b.getTime();
|
|
if (aDate > bDate)
|
|
return 1;
|
|
if (bDate > aDate)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
domain = [min, max];
|
|
// Use compare function to sort numbers numerically
|
|
this.xSet = [...values].sort((a, b) => a - b);
|
|
}
|
|
else {
|
|
domain = values;
|
|
this.xSet = values;
|
|
}
|
|
return domain;
|
|
}
|
|
getYDomain() {
|
|
const domain = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (domain.indexOf(d.value) < 0) {
|
|
domain.push(d.value);
|
|
}
|
|
if (d.min !== undefined) {
|
|
this.hasRange = true;
|
|
if (domain.indexOf(d.min) < 0) {
|
|
domain.push(d.min);
|
|
}
|
|
}
|
|
if (d.max !== undefined) {
|
|
this.hasRange = true;
|
|
if (domain.indexOf(d.max) < 0) {
|
|
domain.push(d.max);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const values = [...domain];
|
|
if (!this.autoScale) {
|
|
values.push(0);
|
|
}
|
|
const min = this.yScaleMin ? this.yScaleMin : Math.min(...values);
|
|
const max = this.yScaleMax ? this.yScaleMax : Math.max(...values);
|
|
return [min, max];
|
|
}
|
|
getSeriesDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
getXScale(domain, width) {
|
|
let scale;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
scale = scaleTime().range([0, width]).domain(domain);
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
scale = scaleLinear().range([0, width]).domain(domain);
|
|
if (this.roundDomains) {
|
|
scale = scale.nice();
|
|
}
|
|
}
|
|
else if (this.scaleType === ScaleType.Ordinal) {
|
|
scale = scalePoint().range([0, width]).padding(0.1).domain(domain);
|
|
}
|
|
return scale;
|
|
}
|
|
getYScale(domain, height) {
|
|
const scale = scaleLinear().range([height, 0]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
updateDomain(domain) {
|
|
this.filteredDomain = domain;
|
|
this.xDomain = this.filteredDomain;
|
|
this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
|
}
|
|
updateHoveredVertical(item) {
|
|
this.hoveredVertical = item.value;
|
|
this.deactivateAll();
|
|
}
|
|
hideCircles() {
|
|
this.hoveredVertical = null;
|
|
this.deactivateAll();
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
trackBy(index, item) {
|
|
return `${item.name}`;
|
|
}
|
|
setColors() {
|
|
let domain;
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
domain = this.seriesDomain;
|
|
}
|
|
else {
|
|
domain = this.yDomain;
|
|
}
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
const opts = {
|
|
scaleType: this.schemeType,
|
|
colors: undefined,
|
|
domain: [],
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
if (opts.scaleType === ScaleType.Ordinal) {
|
|
opts.domain = this.seriesDomain;
|
|
opts.colors = this.colors;
|
|
opts.title = this.legendTitle;
|
|
}
|
|
else {
|
|
opts.domain = this.yDomain;
|
|
opts.colors = this.colors.scale;
|
|
}
|
|
return opts;
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(item) {
|
|
this.deactivateAll();
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
deactivateAll() {
|
|
this.activeEntries = [...this.activeEntries];
|
|
for (const entry of this.activeEntries) {
|
|
this.deactivate.emit({ value: entry, entries: [] });
|
|
}
|
|
this.activeEntries = [];
|
|
}
|
|
}
|
|
LineChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
LineChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LineChartComponent, selector: "ngx-charts-line-chart", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", autoScale: "autoScale", timeline: "timeline", gradient: "gradient", showGridLines: "showGridLines", curve: "curve", activeEntries: "activeEntries", schemeType: "schemeType", rangeFillOpacity: "rangeFillOpacity", trimXAxisTicks: "trimXAxisTicks", trimYAxisTicks: "trimYAxisTicks", rotateXAxisTicks: "rotateXAxisTicks", maxXAxisTickLength: "maxXAxisTickLength", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", xAxisTicks: "xAxisTicks", yAxisTicks: "yAxisTicks", roundDomains: "roundDomains", tooltipDisabled: "tooltipDisabled", showRefLines: "showRefLines", referenceLines: "referenceLines", showRefLabels: "showRefLabels", xScaleMin: "xScaleMin", xScaleMax: "xScaleMax", yScaleMin: "yScaleMin", yScaleMax: "yScaleMax", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseleave": "hideCircles()" } }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }, { propertyName: "seriesTooltipTemplate", first: true, predicate: ["seriesTooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="line-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[referenceLines]="referenceLines"
|
|
[showRefLines]="showRefLines"
|
|
[showRefLabels]="showRefLabels"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy" [@animationState]="'active'">
|
|
<svg:g
|
|
ngx-charts-line-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[hasRange]="hasRange"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-line-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[hasRange]="hasRange"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[activeEntries]="activeEntries"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[scaleType]="scaleType"
|
|
[legend]="legend"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-line-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[hasRange]="hasRange"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: XAxisComponent, selector: "g[ngx-charts-x-axis]", inputs: ["xScale", "dims", "trimTicks", "rotateTicks", "maxTickLength", "tickFormatting", "showGridLines", "showLabel", "labelText", "ticks", "xAxisTickCount", "xOrient", "xAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: LineSeriesComponent, selector: "g[ngx-charts-line-series]", inputs: ["data", "xScale", "yScale", "colors", "scaleType", "curve", "activeEntries", "rangeFillOpacity", "hasRange", "animations"] }, { type: TooltipArea, selector: "g[ngx-charts-tooltip-area]", inputs: ["dims", "xSet", "xScale", "yScale", "results", "colors", "showPercentage", "tooltipDisabled", "tooltipTemplate"], outputs: ["hover"] }, { type: CircleSeriesComponent, selector: "g[ngx-charts-circle-series]", inputs: ["data", "type", "xScale", "yScale", "colors", "scaleType", "visibleValue", "activeEntries", "tooltipDisabled", "tooltipTemplate"], outputs: ["select", "activate", "deactivate"] }, { type: Timeline, selector: "g[ngx-charts-timeline]", inputs: ["view", "results", "scheme", "customColors", "legend", "autoScale", "scaleType", "height"], outputs: ["select", "onDomainChange"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({
|
|
opacity: 0
|
|
}))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-line-chart', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:defs>
|
|
<svg:clipPath [attr.id]="clipPathId">
|
|
<svg:rect
|
|
[attr.width]="dims.width + 10"
|
|
[attr.height]="dims.height + 10"
|
|
[attr.transform]="'translate(-5, -5)'"
|
|
/>
|
|
</svg:clipPath>
|
|
</svg:defs>
|
|
<svg:g [attr.transform]="transform" class="line-chart chart">
|
|
<svg:g
|
|
ngx-charts-x-axis
|
|
*ngIf="xAxis"
|
|
[xScale]="xScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showXAxisLabel"
|
|
[labelText]="xAxisLabel"
|
|
[trimTicks]="trimXAxisTicks"
|
|
[rotateTicks]="rotateXAxisTicks"
|
|
[maxTickLength]="maxXAxisTickLength"
|
|
[tickFormatting]="xAxisTickFormatting"
|
|
[ticks]="xAxisTicks"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateXAxisHeight($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
*ngIf="yAxis"
|
|
[yScale]="yScale"
|
|
[dims]="dims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[ticks]="yAxisTicks"
|
|
[referenceLines]="referenceLines"
|
|
[showRefLines]="showRefLines"
|
|
[showRefLabels]="showRefLabels"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g [attr.clip-path]="clipPath">
|
|
<svg:g *ngIf="!isSSR">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy" [@animationState]="'active'">
|
|
<svg:g
|
|
ngx-charts-line-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[hasRange]="hasRange"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-line-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[hasRange]="hasRange"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
|
<svg:g
|
|
ngx-charts-tooltip-area
|
|
[dims]="dims"
|
|
[xSet]="xSet"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[results]="results"
|
|
[colors]="colors"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="seriesTooltipTemplate"
|
|
(hover)="updateHoveredVertical($event)"
|
|
/>
|
|
|
|
<svg:g *ngFor="let series of results">
|
|
<svg:g
|
|
ngx-charts-circle-series
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[visibleValue]="hoveredVertical"
|
|
[activeEntries]="activeEntries"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-timeline
|
|
*ngIf="timeline && scaleType != 'ordinal'"
|
|
[attr.transform]="timelineTransform"
|
|
[results]="results"
|
|
[view]="[timelineWidth, height]"
|
|
[height]="timelineHeight"
|
|
[scheme]="scheme"
|
|
[customColors]="customColors"
|
|
[scaleType]="scaleType"
|
|
[legend]="legend"
|
|
(onDomainChange)="updateDomain($event)"
|
|
>
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-line-series
|
|
[xScale]="timelineXScale"
|
|
[yScale]="timelineYScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[hasRange]="hasRange"
|
|
[animations]="animations"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({
|
|
opacity: 0
|
|
}))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], autoScale: [{
|
|
type: Input
|
|
}], timeline: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], rangeFillOpacity: [{
|
|
type: Input
|
|
}], trimXAxisTicks: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], rotateXAxisTicks: [{
|
|
type: Input
|
|
}], maxXAxisTickLength: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], xAxisTicks: [{
|
|
type: Input
|
|
}], yAxisTicks: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], showRefLines: [{
|
|
type: Input
|
|
}], referenceLines: [{
|
|
type: Input
|
|
}], showRefLabels: [{
|
|
type: Input
|
|
}], xScaleMin: [{
|
|
type: Input
|
|
}], xScaleMax: [{
|
|
type: Input
|
|
}], yScaleMin: [{
|
|
type: Input
|
|
}], yScaleMax: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], seriesTooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['seriesTooltipTemplate']
|
|
}], hideCircles: [{
|
|
type: HostListener,
|
|
args: ['mouseleave']
|
|
}] } });
|
|
|
|
class LineChartModule {
|
|
}
|
|
LineChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
LineChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineChartModule, declarations: [LineComponent, LineChartComponent, LineSeriesComponent], imports: [ChartCommonModule], exports: [LineComponent, LineChartComponent, LineSeriesComponent] });
|
|
LineChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineChartModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LineChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [LineComponent, LineChartComponent, LineSeriesComponent],
|
|
exports: [LineComponent, LineChartComponent, LineSeriesComponent]
|
|
}]
|
|
}] });
|
|
|
|
class PieLabelComponent {
|
|
constructor(platformId) {
|
|
this.platformId = platformId;
|
|
this.animations = true;
|
|
this.labelTrim = true;
|
|
this.labelTrimSize = 10;
|
|
this.trimLabel = trimLabel;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.setTransforms();
|
|
this.update();
|
|
}
|
|
setTransforms() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.styleTransform = `translate3d(${this.textX}px,${this.textY}px, 0)`;
|
|
this.attrTransform = `translate(${this.textX},${this.textY})`;
|
|
this.textTransition = !this.animations ? null : 'transform 0.75s';
|
|
}
|
|
else {
|
|
const isIE = /(edge|msie|trident)/i.test(navigator.userAgent);
|
|
this.styleTransform = isIE ? null : `translate3d(${this.textX}px,${this.textY}px, 0)`;
|
|
this.attrTransform = !isIE ? null : `translate(${this.textX},${this.textY})`;
|
|
this.textTransition = isIE || !this.animations ? null : 'transform 0.75s';
|
|
}
|
|
}
|
|
update() {
|
|
let startRadius = this.radius;
|
|
if (this.explodeSlices) {
|
|
startRadius = (this.radius * this.value) / this.max;
|
|
}
|
|
const innerArc = arc().innerRadius(startRadius).outerRadius(startRadius);
|
|
// Calculate innerPos then scale outer position to match label position
|
|
const innerPos = innerArc.centroid(this.data);
|
|
let scale = this.data.pos[1] / innerPos[1];
|
|
if (this.data.pos[1] === 0 || innerPos[1] === 0) {
|
|
scale = 1;
|
|
}
|
|
const outerPos = [scale * innerPos[0], scale * innerPos[1]];
|
|
this.line = `M${innerPos}L${outerPos}L${this.data.pos}`;
|
|
}
|
|
get textX() {
|
|
return this.data.pos[0];
|
|
}
|
|
get textY() {
|
|
return this.data.pos[1];
|
|
}
|
|
textAnchor() {
|
|
return this.midAngle(this.data) < Math.PI ? TextAnchor.Start : TextAnchor.End;
|
|
}
|
|
midAngle(d) {
|
|
return d.startAngle + (d.endAngle - d.startAngle) / 2;
|
|
}
|
|
}
|
|
PieLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieLabelComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
PieLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieLabelComponent, selector: "g[ngx-charts-pie-label]", inputs: { data: "data", radius: "radius", label: "label", color: "color", max: "max", value: "value", explodeSlices: "explodeSlices", animations: "animations", labelTrim: "labelTrim", labelTrimSize: "labelTrimSize" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<title>{{ label }}</title>
|
|
<svg:g [attr.transform]="attrTransform" [style.transform]="styleTransform" [style.transition]="textTransition">
|
|
<svg:text
|
|
class="pie-label"
|
|
[class.animation]="animations"
|
|
dy=".35em"
|
|
[style.textAnchor]="textAnchor()"
|
|
[style.shapeRendering]="'crispEdges'"
|
|
>
|
|
{{ labelTrim ? trimLabel(label, labelTrimSize) : label }}
|
|
</svg:text>
|
|
</svg:g>
|
|
<svg:path
|
|
[attr.d]="line"
|
|
[attr.stroke]="color"
|
|
fill="none"
|
|
class="pie-label-line line"
|
|
[class.animation]="animations"
|
|
></svg:path>
|
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieLabelComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-pie-label]',
|
|
template: `
|
|
<title>{{ label }}</title>
|
|
<svg:g [attr.transform]="attrTransform" [style.transform]="styleTransform" [style.transition]="textTransition">
|
|
<svg:text
|
|
class="pie-label"
|
|
[class.animation]="animations"
|
|
dy=".35em"
|
|
[style.textAnchor]="textAnchor()"
|
|
[style.shapeRendering]="'crispEdges'"
|
|
>
|
|
{{ labelTrim ? trimLabel(label, labelTrimSize) : label }}
|
|
</svg:text>
|
|
</svg:g>
|
|
<svg:path
|
|
[attr.d]="line"
|
|
[attr.stroke]="color"
|
|
fill="none"
|
|
class="pie-label-line line"
|
|
[class.animation]="animations"
|
|
></svg:path>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { data: [{
|
|
type: Input
|
|
}], radius: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], color: [{
|
|
type: Input
|
|
}], max: [{
|
|
type: Input
|
|
}], value: [{
|
|
type: Input
|
|
}], explodeSlices: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], labelTrim: [{
|
|
type: Input
|
|
}], labelTrimSize: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class PolarSeriesComponent {
|
|
constructor() {
|
|
this.tooltipDisabled = false;
|
|
this.gradient = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.circleRadius = 3;
|
|
this.barOrientation = BarOrientation;
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.updateGradients();
|
|
const line = this.getLineGenerator();
|
|
const data = this.sortData(this.data.series);
|
|
const seriesName = this.data.name;
|
|
const linearScaleType = this.colors.scaleType === ScaleType.Linear;
|
|
const min = this.yScale.domain()[0];
|
|
this.seriesColor = this.colors.getColor(linearScaleType ? min : seriesName);
|
|
this.path = line(data) || '';
|
|
this.circles = data.map(d => {
|
|
const a = this.getAngle(d);
|
|
const r = this.getRadius(d);
|
|
const value = d.value;
|
|
const color = this.colors.getColor(linearScaleType ? Math.abs(value) : seriesName);
|
|
const cData = Object.assign({}, d, {
|
|
series: seriesName,
|
|
value,
|
|
name: d.name
|
|
});
|
|
return {
|
|
data: cData,
|
|
cx: r * Math.sin(a),
|
|
cy: -r * Math.cos(a),
|
|
value,
|
|
color,
|
|
label: d.name
|
|
};
|
|
});
|
|
this.active = this.isActive(this.data);
|
|
this.inactive = this.isInactive(this.data);
|
|
this.tooltipText = this.tooltipText || (c => this.defaultTooltipText(c));
|
|
}
|
|
getAngle(d) {
|
|
const label = d.name;
|
|
if (this.scaleType === ScaleType.Time) {
|
|
return this.xScale(label);
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
return this.xScale(Number(label));
|
|
}
|
|
return this.xScale(label);
|
|
}
|
|
getRadius(d) {
|
|
return this.yScale(d.value);
|
|
}
|
|
getLineGenerator() {
|
|
return lineRadial()
|
|
.angle(d => this.getAngle(d))
|
|
.radius(d => this.getRadius(d))
|
|
.curve(this.curve);
|
|
}
|
|
sortData(data) {
|
|
if (this.scaleType === ScaleType.Linear) {
|
|
return sortLinear(data, 'name');
|
|
}
|
|
else if (this.scaleType === ScaleType.Time) {
|
|
return sortByTime(data, 'name');
|
|
}
|
|
return sortByDomain(data, 'name', 'asc', this.xScale.domain());
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
isInactive(entry) {
|
|
if (!this.activeEntries || this.activeEntries.length === 0)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name;
|
|
});
|
|
return item === undefined;
|
|
}
|
|
defaultTooltipText({ label, value }) {
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(this.data.name)} • ${escapeLabel(label)}</span>
|
|
<span class="tooltip-val">${value.toLocaleString()}</span>
|
|
`;
|
|
}
|
|
updateGradients() {
|
|
this.hasGradient = this.gradient || this.colors.scaleType === ScaleType.Linear;
|
|
if (!this.hasGradient) {
|
|
return;
|
|
}
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientUrl = `url(#${this.gradientId})`;
|
|
if (this.colors.scaleType === ScaleType.Linear) {
|
|
const values = this.data.series.map(d => d.value);
|
|
const max = Math.max(...values);
|
|
const min = Math.min(...values);
|
|
this.gradientStops = this.colors.getLinearGradientStops(max, min);
|
|
}
|
|
else {
|
|
this.gradientStops = undefined;
|
|
}
|
|
}
|
|
}
|
|
PolarSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
PolarSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PolarSeriesComponent, selector: "g[ngx-charts-polar-series]", inputs: { name: "name", data: "data", xScale: "xScale", yScale: "yScale", colors: "colors", scaleType: "scaleType", curve: "curve", activeEntries: "activeEntries", rangeFillOpacity: "rangeFillOpacity", tooltipDisabled: "tooltipDisabled", tooltipText: "tooltipText", gradient: "gradient", tooltipTemplate: "tooltipTemplate", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g class="polar-charts-series">
|
|
<defs>
|
|
<svg:g
|
|
ngx-charts-svg-radial-gradient
|
|
*ngIf="hasGradient"
|
|
[color]="seriesColor"
|
|
[name]="gradientId"
|
|
[startOpacity]="0.25"
|
|
[endOpacity]="1"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:g
|
|
ngx-charts-line
|
|
class="polar-series-path"
|
|
[path]="path"
|
|
[stroke]="hasGradient ? gradientUrl : seriesColor"
|
|
[class.active]="active"
|
|
[class.inactive]="inactive"
|
|
[attr.fill-opacity]="rangeFillOpacity"
|
|
[fill]="hasGradient ? gradientUrl : seriesColor"
|
|
[animations]="animations"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-circle
|
|
*ngFor="let circle of circles"
|
|
class="circle"
|
|
[cx]="circle.cx"
|
|
[cy]="circle.cy"
|
|
[r]="circleRadius"
|
|
[fill]="circle.color"
|
|
[style.opacity]="inactive ? 0.2 : 1"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
(select)="select.emit(circle.data)"
|
|
(activate)="activate.emit({ name: circle.data.series })"
|
|
(deactivate)="deactivate.emit({ name: circle.data.series })"
|
|
></svg:g>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgRadialGradientComponent, selector: "g[ngx-charts-svg-radial-gradient]", inputs: ["color", "name", "startOpacity", "endOpacity", "cx", "cy", "stops"] }, { type: LineComponent, selector: "g[ngx-charts-line]", inputs: ["path", "stroke", "data", "fill", "animations"] }, { type: CircleComponent, selector: "g[ngx-charts-circle]", inputs: ["cx", "cy", "r", "fill", "stroke", "data", "classNames", "circleOpacity", "pointerEvents"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-polar-series]',
|
|
template: `
|
|
<svg:g class="polar-charts-series">
|
|
<defs>
|
|
<svg:g
|
|
ngx-charts-svg-radial-gradient
|
|
*ngIf="hasGradient"
|
|
[color]="seriesColor"
|
|
[name]="gradientId"
|
|
[startOpacity]="0.25"
|
|
[endOpacity]="1"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:g
|
|
ngx-charts-line
|
|
class="polar-series-path"
|
|
[path]="path"
|
|
[stroke]="hasGradient ? gradientUrl : seriesColor"
|
|
[class.active]="active"
|
|
[class.inactive]="inactive"
|
|
[attr.fill-opacity]="rangeFillOpacity"
|
|
[fill]="hasGradient ? gradientUrl : seriesColor"
|
|
[animations]="animations"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-circle
|
|
*ngFor="let circle of circles"
|
|
class="circle"
|
|
[cx]="circle.cx"
|
|
[cy]="circle.cy"
|
|
[r]="circleRadius"
|
|
[fill]="circle.color"
|
|
[style.opacity]="inactive ? 0.2 : 1"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText(circle)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="circle.data"
|
|
(select)="select.emit(circle.data)"
|
|
(activate)="activate.emit({ name: circle.data.series })"
|
|
(deactivate)="deactivate.emit({ name: circle.data.series })"
|
|
></svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { name: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], xScale: [{
|
|
type: Input
|
|
}], yScale: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], scaleType: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], rangeFillOpacity: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
const twoPI = 2 * Math.PI;
|
|
class PolarChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.showGridLines = true;
|
|
this.curve = curveCardinalClosed;
|
|
this.activeEntries = [];
|
|
this.rangeFillOpacity = 0.15;
|
|
this.trimYAxisTicks = true;
|
|
this.maxYAxisTickLength = 16;
|
|
this.roundDomains = false;
|
|
this.tooltipDisabled = false;
|
|
this.showSeriesOnHover = true;
|
|
this.gradient = false;
|
|
this.yAxisMinScale = 0;
|
|
this.labelTrim = true;
|
|
this.labelTrimSize = 10;
|
|
this.wrapTicks = false;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
// series: any; // ???
|
|
this.margin = [10, 20, 10, 20];
|
|
this.xAxisHeight = 0;
|
|
this.yAxisWidth = 0;
|
|
this.orientation = Orientation;
|
|
this.isSSR = false;
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.isSSR = true;
|
|
}
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.setDims();
|
|
this.setScales();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
this.setTicks();
|
|
}
|
|
setDims() {
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showXAxis: this.xAxis,
|
|
showYAxis: this.yAxis,
|
|
xAxisHeight: this.xAxisHeight,
|
|
yAxisWidth: this.yAxisWidth,
|
|
showXLabel: this.showXAxisLabel,
|
|
showYLabel: this.showYAxisLabel,
|
|
showLegend: this.legend,
|
|
legendType: this.schemeType,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
const halfWidth = Math.floor(this.dims.width / 2);
|
|
const halfHeight = Math.floor(this.dims.height / 2);
|
|
const outerRadius = (this.outerRadius = Math.min(halfHeight / 1.5, halfWidth / 1.5));
|
|
const yOffset = Math.max(0, halfHeight - outerRadius);
|
|
this.yAxisDims = {
|
|
...this.dims,
|
|
width: halfWidth
|
|
};
|
|
this.transform = `translate(${this.dims.xOffset}, ${this.margin[0]})`;
|
|
this.transformYAxis = `translate(0, ${yOffset})`;
|
|
this.labelOffset = this.dims.height + 40;
|
|
this.transformPlot = `translate(${halfWidth}, ${halfHeight})`;
|
|
}
|
|
setScales() {
|
|
const xValues = this.getXValues();
|
|
this.scaleType = getScaleType(xValues);
|
|
this.xDomain = this.filteredDomain || this.getXDomain(xValues);
|
|
this.yDomain = this.getYDomain();
|
|
this.seriesDomain = this.getSeriesDomain();
|
|
this.xScale = this.getXScale(this.xDomain, twoPI);
|
|
this.yScale = this.getYScale(this.yDomain, this.outerRadius);
|
|
this.yAxisScale = this.getYScale(this.yDomain.reverse(), this.outerRadius);
|
|
}
|
|
setTicks() {
|
|
let tickFormat;
|
|
if (this.xAxisTickFormatting) {
|
|
tickFormat = this.xAxisTickFormatting;
|
|
}
|
|
else if (this.xScale.tickFormat) {
|
|
tickFormat = this.xScale.tickFormat.apply(this.xScale, [5]);
|
|
}
|
|
else {
|
|
tickFormat = d => {
|
|
if (isDate(d)) {
|
|
return d.toLocaleDateString();
|
|
}
|
|
return d.toLocaleString();
|
|
};
|
|
}
|
|
const outerRadius = this.outerRadius;
|
|
const s = 1.1;
|
|
this.thetaTicks = this.xDomain.map(d => {
|
|
const startAngle = this.xScale(d);
|
|
const dd = s * outerRadius * (startAngle > Math.PI ? -1 : 1);
|
|
const label = tickFormat(d);
|
|
const startPos = [outerRadius * Math.sin(startAngle), -outerRadius * Math.cos(startAngle)];
|
|
const pos = [dd, s * startPos[1]];
|
|
return {
|
|
innerRadius: 0,
|
|
outerRadius,
|
|
startAngle,
|
|
endAngle: startAngle,
|
|
value: outerRadius,
|
|
label,
|
|
startPos,
|
|
pos
|
|
};
|
|
});
|
|
const minDistance = 10;
|
|
/* from pie chart, abstract out -*/
|
|
for (let i = 0; i < this.thetaTicks.length - 1; i++) {
|
|
const a = this.thetaTicks[i];
|
|
for (let j = i + 1; j < this.thetaTicks.length; j++) {
|
|
const b = this.thetaTicks[j];
|
|
// if they're on the same side
|
|
if (b.pos[0] * a.pos[0] > 0) {
|
|
// if they're overlapping
|
|
const o = minDistance - Math.abs(b.pos[1] - a.pos[1]);
|
|
if (o > 0) {
|
|
// push the second up or down
|
|
b.pos[1] += Math.sign(b.pos[0]) * o;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.radiusTicks = this.yAxisScale.ticks(Math.floor(this.dims.height / 50)).map(d => this.yScale(d));
|
|
}
|
|
getXValues() {
|
|
const values = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (!values.includes(d.name)) {
|
|
values.push(d.name);
|
|
}
|
|
}
|
|
}
|
|
return values;
|
|
}
|
|
getXDomain(values = this.getXValues()) {
|
|
if (this.scaleType === ScaleType.Time) {
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
return [min, max];
|
|
}
|
|
else if (this.scaleType === ScaleType.Linear) {
|
|
values = values.map(v => Number(v));
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
return [min, max];
|
|
}
|
|
return values;
|
|
}
|
|
getYValues() {
|
|
const domain = [];
|
|
for (const results of this.results) {
|
|
for (const d of results.series) {
|
|
if (domain.indexOf(d.value) < 0) {
|
|
domain.push(d.value);
|
|
}
|
|
if (d.min !== undefined) {
|
|
if (domain.indexOf(d.min) < 0) {
|
|
domain.push(d.min);
|
|
}
|
|
}
|
|
if (d.max !== undefined) {
|
|
if (domain.indexOf(d.max) < 0) {
|
|
domain.push(d.max);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return domain;
|
|
}
|
|
getYDomain(domain = this.getYValues()) {
|
|
let min = Math.min(...domain);
|
|
const max = Math.max(this.yAxisMinScale, ...domain);
|
|
min = Math.max(0, min);
|
|
if (!this.autoScale) {
|
|
min = Math.min(0, min);
|
|
}
|
|
return [min, max];
|
|
}
|
|
getSeriesDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
getXScale(domain, width) {
|
|
switch (this.scaleType) {
|
|
case ScaleType.Time:
|
|
return scaleTime().range([0, width]).domain(domain);
|
|
case ScaleType.Linear: {
|
|
const scale = scaleLinear().range([0, width]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
default:
|
|
return scalePoint()
|
|
.range([0, width - twoPI / domain.length])
|
|
.padding(0)
|
|
.domain(domain);
|
|
}
|
|
}
|
|
getYScale(domain, height) {
|
|
const scale = scaleLinear().range([0, height]).domain(domain);
|
|
return this.roundDomains ? scale.nice() : scale;
|
|
}
|
|
onClick(data, series) {
|
|
if (series) {
|
|
data.series = series.name;
|
|
}
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
const domain = this.schemeType === ScaleType.Ordinal ? this.seriesDomain : this.yDomain.reverse();
|
|
this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
if (this.schemeType === ScaleType.Ordinal) {
|
|
return {
|
|
scaleType: this.schemeType,
|
|
colors: this.colors,
|
|
domain: this.seriesDomain,
|
|
title: this.legendTitle,
|
|
position: this.legendPosition
|
|
};
|
|
}
|
|
return {
|
|
scaleType: this.schemeType,
|
|
colors: this.colors.scale,
|
|
domain: this.yDomain,
|
|
title: undefined,
|
|
position: this.legendPosition
|
|
};
|
|
}
|
|
updateYAxisWidth({ width }) {
|
|
this.yAxisWidth = width;
|
|
this.update();
|
|
}
|
|
updateXAxisHeight({ height }) {
|
|
this.xAxisHeight = height;
|
|
this.update();
|
|
}
|
|
onActivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = this.showSeriesOnHover ? [item, ...this.activeEntries] : this.activeEntries;
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
deactivateAll() {
|
|
this.activeEntries = [...this.activeEntries];
|
|
for (const entry of this.activeEntries) {
|
|
this.deactivate.emit({ value: entry, entries: [] });
|
|
}
|
|
this.activeEntries = [];
|
|
}
|
|
trackBy(index, item) {
|
|
return `${item.name}`;
|
|
}
|
|
}
|
|
PolarChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
PolarChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PolarChartComponent, selector: "ngx-charts-polar-chart", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", xAxis: "xAxis", yAxis: "yAxis", showXAxisLabel: "showXAxisLabel", showYAxisLabel: "showYAxisLabel", xAxisLabel: "xAxisLabel", yAxisLabel: "yAxisLabel", autoScale: "autoScale", showGridLines: "showGridLines", curve: "curve", activeEntries: "activeEntries", schemeType: "schemeType", rangeFillOpacity: "rangeFillOpacity", trimYAxisTicks: "trimYAxisTicks", maxYAxisTickLength: "maxYAxisTickLength", xAxisTickFormatting: "xAxisTickFormatting", yAxisTickFormatting: "yAxisTickFormatting", roundDomains: "roundDomains", tooltipDisabled: "tooltipDisabled", showSeriesOnHover: "showSeriesOnHover", gradient: "gradient", yAxisMinScale: "yAxisMinScale", labelTrim: "labelTrim", labelTrimSize: "labelTrimSize", wrapTicks: "wrapTicks" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:g class="polar-chart chart" [attr.transform]="transform">
|
|
<svg:g [attr.transform]="transformPlot">
|
|
<svg:circle class="polar-chart-background" cx="0" cy="0" [attr.r]="this.outerRadius" />
|
|
<svg:g *ngIf="showGridLines">
|
|
<svg:circle
|
|
*ngFor="let r of radiusTicks"
|
|
class="gridline-path radial-gridline-path"
|
|
cx="0"
|
|
cy="0"
|
|
[attr.r]="r"
|
|
/>
|
|
</svg:g>
|
|
<svg:g *ngIf="xAxis">
|
|
<svg:g
|
|
ngx-charts-pie-label
|
|
*ngFor="let tick of thetaTicks"
|
|
[data]="tick"
|
|
[radius]="outerRadius"
|
|
[label]="tick.label"
|
|
[max]="outerRadius"
|
|
[value]="showGridLines ? 1 : outerRadius"
|
|
[explodeSlices]="true"
|
|
[animations]="animations"
|
|
[labelTrim]="labelTrim"
|
|
[labelTrimSize]="labelTrimSize"
|
|
></svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
[attr.transform]="transformYAxis"
|
|
*ngIf="yAxis"
|
|
[yScale]="yAxisScale"
|
|
[dims]="yAxisDims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-axis-label
|
|
*ngIf="xAxis && showXAxisLabel"
|
|
[label]="xAxisLabel"
|
|
[offset]="labelOffset"
|
|
[orient]="orientation.Bottom"
|
|
[height]="dims.height"
|
|
[width]="dims.width"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR" [attr.transform]="transformPlot">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy" [@animationState]="'active'">
|
|
<svg:g
|
|
ngx-charts-polar-series
|
|
[gradient]="gradient"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR" [attr.transform]="transformPlot">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-polar-series
|
|
[gradient]="gradient"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".pie-label{font-size:11px}.pie-label.animation{animation:.75s ease-in fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.pie-label-line{stroke-dasharray:100%}.pie-label-line.animation{animation:3s linear drawOut;transition:d .75s}@keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}\n", ".polar-chart .polar-chart-background{fill:none}.polar-chart .radial-gridline-path{stroke-dasharray:10 10;fill:none}.polar-chart .pie-label-line{stroke:#2f3646}.polar-charts-series .polar-series-area,.polar-series-path{pointer-events:none}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: PieLabelComponent, selector: "g[ngx-charts-pie-label]", inputs: ["data", "radius", "label", "color", "max", "value", "explodeSlices", "animations", "labelTrim", "labelTrimSize"] }, { type: YAxisComponent, selector: "g[ngx-charts-y-axis]", inputs: ["yScale", "dims", "trimTicks", "maxTickLength", "tickFormatting", "ticks", "showGridLines", "showLabel", "labelText", "yAxisTickCount", "yOrient", "referenceLines", "showRefLines", "showRefLabels", "yAxisOffset", "wrapTicks"], outputs: ["dimensionsChanged"] }, { type: AxisLabelComponent, selector: "g[ngx-charts-axis-label]", inputs: ["orient", "label", "offset", "width", "height"] }, { type: PolarSeriesComponent, selector: "g[ngx-charts-polar-series]", inputs: ["name", "data", "xScale", "yScale", "colors", "scaleType", "curve", "activeEntries", "rangeFillOpacity", "tooltipDisabled", "tooltipText", "gradient", "tooltipTemplate", "animations"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({
|
|
opacity: 0
|
|
}))
|
|
])
|
|
])
|
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-polar-chart', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:g class="polar-chart chart" [attr.transform]="transform">
|
|
<svg:g [attr.transform]="transformPlot">
|
|
<svg:circle class="polar-chart-background" cx="0" cy="0" [attr.r]="this.outerRadius" />
|
|
<svg:g *ngIf="showGridLines">
|
|
<svg:circle
|
|
*ngFor="let r of radiusTicks"
|
|
class="gridline-path radial-gridline-path"
|
|
cx="0"
|
|
cy="0"
|
|
[attr.r]="r"
|
|
/>
|
|
</svg:g>
|
|
<svg:g *ngIf="xAxis">
|
|
<svg:g
|
|
ngx-charts-pie-label
|
|
*ngFor="let tick of thetaTicks"
|
|
[data]="tick"
|
|
[radius]="outerRadius"
|
|
[label]="tick.label"
|
|
[max]="outerRadius"
|
|
[value]="showGridLines ? 1 : outerRadius"
|
|
[explodeSlices]="true"
|
|
[animations]="animations"
|
|
[labelTrim]="labelTrim"
|
|
[labelTrimSize]="labelTrimSize"
|
|
></svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g
|
|
ngx-charts-y-axis
|
|
[attr.transform]="transformYAxis"
|
|
*ngIf="yAxis"
|
|
[yScale]="yAxisScale"
|
|
[dims]="yAxisDims"
|
|
[showGridLines]="showGridLines"
|
|
[showLabel]="showYAxisLabel"
|
|
[labelText]="yAxisLabel"
|
|
[trimTicks]="trimYAxisTicks"
|
|
[maxTickLength]="maxYAxisTickLength"
|
|
[tickFormatting]="yAxisTickFormatting"
|
|
[wrapTicks]="wrapTicks"
|
|
(dimensionsChanged)="updateYAxisWidth($event)"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-axis-label
|
|
*ngIf="xAxis && showXAxisLabel"
|
|
[label]="xAxisLabel"
|
|
[offset]="labelOffset"
|
|
[orient]="orientation.Bottom"
|
|
[height]="dims.height"
|
|
[width]="dims.width"
|
|
></svg:g>
|
|
<svg:g *ngIf="!isSSR" [attr.transform]="transformPlot">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy" [@animationState]="'active'">
|
|
<svg:g
|
|
ngx-charts-polar-series
|
|
[gradient]="gradient"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
<svg:g *ngIf="isSSR" [attr.transform]="transformPlot">
|
|
<svg:g *ngFor="let series of results; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-polar-series
|
|
[gradient]="gradient"
|
|
[xScale]="xScale"
|
|
[yScale]="yScale"
|
|
[colors]="colors"
|
|
[data]="series"
|
|
[activeEntries]="activeEntries"
|
|
[scaleType]="scaleType"
|
|
[curve]="curve"
|
|
[rangeFillOpacity]="rangeFillOpacity"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
|
|
trigger('animationState', [
|
|
transition(':leave', [
|
|
style({
|
|
opacity: 1
|
|
}),
|
|
animate(500, style({
|
|
opacity: 0
|
|
}))
|
|
])
|
|
])
|
|
], styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".pie-label{font-size:11px}.pie-label.animation{animation:.75s ease-in fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.pie-label-line{stroke-dasharray:100%}.pie-label-line.animation{animation:3s linear drawOut;transition:d .75s}@keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}\n", ".polar-chart .polar-chart-background{fill:none}.polar-chart .radial-gridline-path{stroke-dasharray:10 10;fill:none}.polar-chart .pie-label-line{stroke:#2f3646}.polar-charts-series .polar-series-area,.polar-series-path{pointer-events:none}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], xAxis: [{
|
|
type: Input
|
|
}], yAxis: [{
|
|
type: Input
|
|
}], showXAxisLabel: [{
|
|
type: Input
|
|
}], showYAxisLabel: [{
|
|
type: Input
|
|
}], xAxisLabel: [{
|
|
type: Input
|
|
}], yAxisLabel: [{
|
|
type: Input
|
|
}], autoScale: [{
|
|
type: Input
|
|
}], showGridLines: [{
|
|
type: Input
|
|
}], curve: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], schemeType: [{
|
|
type: Input
|
|
}], rangeFillOpacity: [{
|
|
type: Input
|
|
}], trimYAxisTicks: [{
|
|
type: Input
|
|
}], maxYAxisTickLength: [{
|
|
type: Input
|
|
}], xAxisTickFormatting: [{
|
|
type: Input
|
|
}], yAxisTickFormatting: [{
|
|
type: Input
|
|
}], roundDomains: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], showSeriesOnHover: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], yAxisMinScale: [{
|
|
type: Input
|
|
}], labelTrim: [{
|
|
type: Input
|
|
}], labelTrimSize: [{
|
|
type: Input
|
|
}], wrapTicks: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class PieArcComponent {
|
|
constructor(element) {
|
|
this.startAngle = 0;
|
|
this.endAngle = Math.PI * 2;
|
|
this.cornerRadius = 0;
|
|
this.explodeSlices = false;
|
|
this.gradient = false;
|
|
this.animate = true;
|
|
this.pointerEvents = true;
|
|
this.isActive = false;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.dblclick = new EventEmitter();
|
|
this.barOrientation = BarOrientation;
|
|
this.initialized = false;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
getGradient() {
|
|
return this.gradient ? this.gradientFill : this.fill;
|
|
}
|
|
getPointerEvents() {
|
|
return this.pointerEvents ? 'auto' : 'none';
|
|
}
|
|
update() {
|
|
const calc = this.calculateArc();
|
|
this.startOpacity = 0.5;
|
|
this.radialGradientId = 'linearGrad' + id().toString();
|
|
this.gradientFill = `url(#${this.radialGradientId})`;
|
|
if (this.animate) {
|
|
if (this.initialized) {
|
|
this.updateAnimation();
|
|
}
|
|
else {
|
|
this.loadAnimation();
|
|
this.initialized = true;
|
|
}
|
|
}
|
|
else {
|
|
this.path = calc.startAngle(this.startAngle).endAngle(this.endAngle)();
|
|
}
|
|
}
|
|
calculateArc() {
|
|
let outerRadius = this.outerRadius;
|
|
if (this.explodeSlices && this.innerRadius === 0) {
|
|
outerRadius = (this.outerRadius * this.value) / this.max;
|
|
}
|
|
return arc().innerRadius(this.innerRadius).outerRadius(outerRadius).cornerRadius(this.cornerRadius);
|
|
}
|
|
loadAnimation() {
|
|
const node = select(this.element)
|
|
.selectAll('.arc')
|
|
.data([{ startAngle: this.startAngle, endAngle: this.endAngle }]);
|
|
const calc = this.calculateArc();
|
|
node
|
|
.transition()
|
|
.attrTween('d', function (d) {
|
|
this._current = this._current || d;
|
|
const copyOfD = Object.assign({}, d);
|
|
copyOfD.endAngle = copyOfD.startAngle;
|
|
const interpolater = interpolate(copyOfD, copyOfD);
|
|
this._current = interpolater(0);
|
|
return function (t) {
|
|
return calc(interpolater(t));
|
|
};
|
|
})
|
|
.transition()
|
|
.duration(750)
|
|
.attrTween('d', function (d) {
|
|
this._current = this._current || d;
|
|
const interpolater = interpolate(this._current, d);
|
|
this._current = interpolater(0);
|
|
return function (t) {
|
|
return calc(interpolater(t));
|
|
};
|
|
});
|
|
}
|
|
updateAnimation() {
|
|
const node = select(this.element)
|
|
.selectAll('.arc')
|
|
.data([{ startAngle: this.startAngle, endAngle: this.endAngle }]);
|
|
const calc = this.calculateArc();
|
|
node
|
|
.transition()
|
|
.duration(750)
|
|
.attrTween('d', function (d) {
|
|
this._current = this._current || d;
|
|
const interpolater = interpolate(this._current, d);
|
|
this._current = interpolater(0);
|
|
return function (t) {
|
|
return calc(interpolater(t));
|
|
};
|
|
});
|
|
}
|
|
onClick() {
|
|
clearTimeout(this._timeout);
|
|
this._timeout = setTimeout(() => this.select.emit(this.data), 200);
|
|
}
|
|
onDblClick(event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
clearTimeout(this._timeout);
|
|
this.dblclick.emit({
|
|
data: this.data,
|
|
nativeEvent: event
|
|
});
|
|
}
|
|
}
|
|
PieArcComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieArcComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
PieArcComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieArcComponent, selector: "g[ngx-charts-pie-arc]", inputs: { fill: "fill", startAngle: "startAngle", endAngle: "endAngle", innerRadius: "innerRadius", outerRadius: "outerRadius", cornerRadius: "cornerRadius", value: "value", max: "max", data: "data", explodeSlices: "explodeSlices", gradient: "gradient", animate: "animate", pointerEvents: "pointerEvents", isActive: "isActive" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate", dblclick: "dblclick" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g class="arc-group">
|
|
<svg:defs *ngIf="gradient">
|
|
<svg:g ngx-charts-svg-radial-gradient [color]="fill" [name]="radialGradientId" [startOpacity]="startOpacity" />
|
|
</svg:defs>
|
|
<svg:path
|
|
[attr.d]="path"
|
|
class="arc"
|
|
[class.active]="isActive"
|
|
[attr.fill]="getGradient()"
|
|
(click)="onClick()"
|
|
(dblclick)="onDblClick($event)"
|
|
(mouseenter)="activate.emit(data)"
|
|
(mouseleave)="deactivate.emit(data)"
|
|
[style.pointer-events]="getPointerEvents()"
|
|
/>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgRadialGradientComponent, selector: "g[ngx-charts-svg-radial-gradient]", inputs: ["color", "name", "startOpacity", "endOpacity", "cx", "cy", "stops"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieArcComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-pie-arc]',
|
|
template: `
|
|
<svg:g class="arc-group">
|
|
<svg:defs *ngIf="gradient">
|
|
<svg:g ngx-charts-svg-radial-gradient [color]="fill" [name]="radialGradientId" [startOpacity]="startOpacity" />
|
|
</svg:defs>
|
|
<svg:path
|
|
[attr.d]="path"
|
|
class="arc"
|
|
[class.active]="isActive"
|
|
[attr.fill]="getGradient()"
|
|
(click)="onClick()"
|
|
(dblclick)="onDblClick($event)"
|
|
(mouseenter)="activate.emit(data)"
|
|
(mouseleave)="deactivate.emit(data)"
|
|
[style.pointer-events]="getPointerEvents()"
|
|
/>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { fill: [{
|
|
type: Input
|
|
}], startAngle: [{
|
|
type: Input
|
|
}], endAngle: [{
|
|
type: Input
|
|
}], innerRadius: [{
|
|
type: Input
|
|
}], outerRadius: [{
|
|
type: Input
|
|
}], cornerRadius: [{
|
|
type: Input
|
|
}], value: [{
|
|
type: Input
|
|
}], max: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], explodeSlices: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], animate: [{
|
|
type: Input
|
|
}], pointerEvents: [{
|
|
type: Input
|
|
}], isActive: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], dblclick: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class PieSeriesComponent {
|
|
constructor() {
|
|
this.series = [];
|
|
this.innerRadius = 60;
|
|
this.outerRadius = 80;
|
|
this.trimLabels = true;
|
|
this.maxLabelLength = 10;
|
|
this.tooltipDisabled = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.dblclick = new EventEmitter();
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
const pieGenerator = pie()
|
|
.value(d => d.value)
|
|
.sort(null);
|
|
const arcData = pieGenerator(this.series);
|
|
this.max = max(arcData, d => {
|
|
return d.value;
|
|
});
|
|
this.data = this.calculateLabelPositions(arcData);
|
|
this.tooltipText = this.tooltipText || this.defaultTooltipText;
|
|
}
|
|
midAngle(d) {
|
|
return d.startAngle + (d.endAngle - d.startAngle) / 2;
|
|
}
|
|
outerArc() {
|
|
const factor = 1.5;
|
|
return arc()
|
|
.innerRadius(this.outerRadius * factor)
|
|
.outerRadius(this.outerRadius * factor);
|
|
}
|
|
calculateLabelPositions(pieData) {
|
|
const factor = 1.5;
|
|
const minDistance = 10;
|
|
const labelPositions = pieData;
|
|
labelPositions.forEach(d => {
|
|
d.pos = this.outerArc().centroid(d);
|
|
d.pos[0] = factor * this.outerRadius * (this.midAngle(d) < Math.PI ? 1 : -1);
|
|
});
|
|
for (let i = 0; i < labelPositions.length - 1; i++) {
|
|
const a = labelPositions[i];
|
|
if (!this.labelVisible(a)) {
|
|
continue;
|
|
}
|
|
for (let j = i + 1; j < labelPositions.length; j++) {
|
|
const b = labelPositions[j];
|
|
if (!this.labelVisible(b)) {
|
|
continue;
|
|
}
|
|
// if they're on the same side
|
|
if (b.pos[0] * a.pos[0] > 0) {
|
|
// if they're overlapping
|
|
const o = minDistance - Math.abs(b.pos[1] - a.pos[1]);
|
|
if (o > 0) {
|
|
// push the second up or down
|
|
b.pos[1] += Math.sign(b.pos[0]) * o;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return labelPositions;
|
|
}
|
|
labelVisible(myArc) {
|
|
return this.showLabels && myArc.endAngle - myArc.startAngle > Math.PI / 30;
|
|
}
|
|
getTooltipTitle(a) {
|
|
return this.tooltipTemplate ? undefined : this.tooltipText(a);
|
|
}
|
|
labelText(myArc) {
|
|
if (this.labelFormatting) {
|
|
return this.labelFormatting(myArc.data.name);
|
|
}
|
|
return this.label(myArc);
|
|
}
|
|
label(myArc) {
|
|
return formatLabel(myArc.data.name);
|
|
}
|
|
defaultTooltipText(myArc) {
|
|
const label = this.label(myArc);
|
|
const val = formatLabel(myArc.data.value);
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(label)}</span>
|
|
<span class="tooltip-val">${val}</span>
|
|
`;
|
|
}
|
|
color(myArc) {
|
|
return this.colors.getColor(this.label(myArc));
|
|
}
|
|
trackBy(index, item) {
|
|
return item.data.name;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name && entry.series === d.series;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
}
|
|
PieSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
PieSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieSeriesComponent, selector: "g[ngx-charts-pie-series]", inputs: { colors: "colors", series: "series", dims: "dims", innerRadius: "innerRadius", outerRadius: "outerRadius", explodeSlices: "explodeSlices", showLabels: "showLabels", gradient: "gradient", activeEntries: "activeEntries", labelFormatting: "labelFormatting", trimLabels: "trimLabels", maxLabelLength: "maxLabelLength", tooltipText: "tooltipText", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate", dblclick: "dblclick" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g *ngFor="let arc of data; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-pie-label
|
|
*ngIf="labelVisible(arc)"
|
|
[data]="arc"
|
|
[radius]="outerRadius"
|
|
[color]="color(arc)"
|
|
[label]="labelText(arc)"
|
|
[labelTrim]="trimLabels"
|
|
[labelTrimSize]="maxLabelLength"
|
|
[max]="max"
|
|
[value]="arc.value"
|
|
[explodeSlices]="explodeSlices"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
[startAngle]="arc.startAngle"
|
|
[endAngle]="arc.endAngle"
|
|
[innerRadius]="innerRadius"
|
|
[outerRadius]="outerRadius"
|
|
[fill]="color(arc)"
|
|
[value]="arc.data.value"
|
|
[gradient]="gradient"
|
|
[data]="arc.data"
|
|
[max]="max"
|
|
[explodeSlices]="explodeSlices"
|
|
[isActive]="isActive(arc.data)"
|
|
[animate]="animations"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
(dblclick)="dblclick.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="getTooltipTitle(arc)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="arc.data"
|
|
></svg:g>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: PieLabelComponent, selector: "g[ngx-charts-pie-label]", inputs: ["data", "radius", "label", "color", "max", "value", "explodeSlices", "animations", "labelTrim", "labelTrimSize"] }, { type: PieArcComponent, selector: "g[ngx-charts-pie-arc]", inputs: ["fill", "startAngle", "endAngle", "innerRadius", "outerRadius", "cornerRadius", "value", "max", "data", "explodeSlices", "gradient", "animate", "pointerEvents", "isActive"], outputs: ["select", "activate", "deactivate", "dblclick"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-pie-series]',
|
|
template: `
|
|
<svg:g *ngFor="let arc of data; trackBy: trackBy">
|
|
<svg:g
|
|
ngx-charts-pie-label
|
|
*ngIf="labelVisible(arc)"
|
|
[data]="arc"
|
|
[radius]="outerRadius"
|
|
[color]="color(arc)"
|
|
[label]="labelText(arc)"
|
|
[labelTrim]="trimLabels"
|
|
[labelTrimSize]="maxLabelLength"
|
|
[max]="max"
|
|
[value]="arc.value"
|
|
[explodeSlices]="explodeSlices"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
[startAngle]="arc.startAngle"
|
|
[endAngle]="arc.endAngle"
|
|
[innerRadius]="innerRadius"
|
|
[outerRadius]="outerRadius"
|
|
[fill]="color(arc)"
|
|
[value]="arc.data.value"
|
|
[gradient]="gradient"
|
|
[data]="arc.data"
|
|
[max]="max"
|
|
[explodeSlices]="explodeSlices"
|
|
[isActive]="isActive(arc.data)"
|
|
[animate]="animations"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
(dblclick)="dblclick.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="getTooltipTitle(arc)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="arc.data"
|
|
></svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { colors: [{
|
|
type: Input
|
|
}], series: [{
|
|
type: Input
|
|
}], dims: [{
|
|
type: Input
|
|
}], innerRadius: [{
|
|
type: Input
|
|
}], outerRadius: [{
|
|
type: Input
|
|
}], explodeSlices: [{
|
|
type: Input
|
|
}], showLabels: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], trimLabels: [{
|
|
type: Input
|
|
}], maxLabelLength: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], dblclick: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class AdvancedPieChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.activeEntries = [];
|
|
this.tooltipDisabled = false;
|
|
this.label = 'Total';
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [20, 20, 20, 20];
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: (this.width * 4) / 12.0,
|
|
height: this.height,
|
|
margins: this.margin
|
|
});
|
|
this.formatDates();
|
|
this.domain = this.getDomain();
|
|
this.setColors();
|
|
const xOffset = this.dims.width / 2;
|
|
const yOffset = this.margin[0] + this.dims.height / 2;
|
|
this.legendWidth = this.width - this.dims.width - this.margin[1];
|
|
this.outerRadius = Math.min(this.dims.width, this.dims.height) / 2.5;
|
|
this.innerRadius = this.outerRadius * 0.75;
|
|
this.transform = `translate(${xOffset} , ${yOffset})`;
|
|
}
|
|
getDomain() {
|
|
return this.results.map(d => d.label);
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
|
}
|
|
onActivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
AdvancedPieChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AdvancedPieChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
AdvancedPieChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: AdvancedPieChartComponent, selector: "ngx-charts-advanced-pie-chart", inputs: { gradient: "gradient", activeEntries: "activeEntries", tooltipDisabled: "tooltipDisabled", tooltipText: "tooltipText", label: "label", valueFormatting: "valueFormatting", nameFormatting: "nameFormatting", percentageFormatting: "percentageFormatting" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<div [style.width.px]="width" [style.height.px]="height">
|
|
<div class="advanced-pie chart" [style.width.px]="dims.width" [style.height.px]="dims.height">
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="pie chart">
|
|
<svg:g
|
|
ngx-charts-pie-series
|
|
[colors]="colors"
|
|
[series]="results"
|
|
[innerRadius]="innerRadius"
|
|
[activeEntries]="activeEntries"
|
|
[outerRadius]="outerRadius"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipText]="tooltipText"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
</div>
|
|
<div class="advanced-pie-legend-wrapper" [style.width.px]="width - dims.width" [style.height.px]="height">
|
|
<ngx-charts-advanced-legend
|
|
[data]="results"
|
|
[colors]="colors"
|
|
[width]="width - dims.width - margin[1]"
|
|
[label]="label"
|
|
[animations]="animations"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="nameFormatting"
|
|
[percentageFormatting]="percentageFormatting"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event, true)"
|
|
(deactivate)="onDeactivate($event, true)"
|
|
>
|
|
</ngx-charts-advanced-legend>
|
|
</div>
|
|
</div>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".advanced-pie{display:inline-block;float:left}.advanced-pie-legend-wrapper{display:inline-block}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: PieSeriesComponent, selector: "g[ngx-charts-pie-series]", inputs: ["colors", "series", "dims", "innerRadius", "outerRadius", "explodeSlices", "showLabels", "gradient", "activeEntries", "labelFormatting", "trimLabels", "maxLabelLength", "tooltipText", "tooltipDisabled", "tooltipTemplate", "animations"], outputs: ["select", "activate", "deactivate", "dblclick"] }, { type: AdvancedLegendComponent, selector: "ngx-charts-advanced-legend", inputs: ["width", "data", "colors", "label", "animations", "valueFormatting", "labelFormatting", "percentageFormatting"], outputs: ["select", "activate", "deactivate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AdvancedPieChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-advanced-pie-chart', template: `
|
|
<div [style.width.px]="width" [style.height.px]="height">
|
|
<div class="advanced-pie chart" [style.width.px]="dims.width" [style.height.px]="dims.height">
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="pie chart">
|
|
<svg:g
|
|
ngx-charts-pie-series
|
|
[colors]="colors"
|
|
[series]="results"
|
|
[innerRadius]="innerRadius"
|
|
[activeEntries]="activeEntries"
|
|
[outerRadius]="outerRadius"
|
|
[gradient]="gradient"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipText]="tooltipText"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
</div>
|
|
<div class="advanced-pie-legend-wrapper" [style.width.px]="width - dims.width" [style.height.px]="height">
|
|
<ngx-charts-advanced-legend
|
|
[data]="results"
|
|
[colors]="colors"
|
|
[width]="width - dims.width - margin[1]"
|
|
[label]="label"
|
|
[animations]="animations"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="nameFormatting"
|
|
[percentageFormatting]="percentageFormatting"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event, true)"
|
|
(deactivate)="onDeactivate($event, true)"
|
|
>
|
|
</ngx-charts-advanced-legend>
|
|
</div>
|
|
</div>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".advanced-pie{display:inline-block;float:left}.advanced-pie-legend-wrapper{display:inline-block}\n"] }]
|
|
}], propDecorators: { gradient: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], nameFormatting: [{
|
|
type: Input
|
|
}], percentageFormatting: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class PieChartComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.labels = false;
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.explodeSlices = false;
|
|
this.doughnut = false;
|
|
this.arcWidth = 0.25;
|
|
this.activeEntries = [];
|
|
this.tooltipDisabled = false;
|
|
this.trimLabels = true;
|
|
this.maxLabelLength = 10;
|
|
this.dblclick = new EventEmitter();
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (this.labels && this.hasNoOptionalMarginsSet()) {
|
|
this.margins = [30, 80, 30, 80];
|
|
}
|
|
else if (!this.labels && this.hasNoOptionalMarginsSet()) {
|
|
// default value for margins
|
|
this.margins = [20, 20, 20, 20];
|
|
}
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margins,
|
|
showLegend: this.legend,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.formatDates();
|
|
const xOffset = this.margins[3] + this.dims.width / 2;
|
|
const yOffset = this.margins[0] + this.dims.height / 2;
|
|
this.translation = `translate(${xOffset}, ${yOffset})`;
|
|
this.outerRadius = Math.min(this.dims.width, this.dims.height);
|
|
if (this.labels) {
|
|
// make room for labels
|
|
this.outerRadius /= 3;
|
|
}
|
|
else {
|
|
this.outerRadius /= 2;
|
|
}
|
|
this.innerRadius = 0;
|
|
if (this.doughnut) {
|
|
this.innerRadius = this.outerRadius * (1 - this.arcWidth);
|
|
}
|
|
this.domain = this.getDomain();
|
|
// sort data according to domain
|
|
this.data = this.results.sort((a, b) => {
|
|
return this.domain.indexOf(a.name) - this.domain.indexOf(b.name);
|
|
});
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
}
|
|
getDomain() {
|
|
return this.results.map(d => d.label);
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
|
}
|
|
getLegendOptions() {
|
|
return {
|
|
scaleType: ScaleType.Ordinal,
|
|
domain: this.domain,
|
|
colors: this.colors,
|
|
title: this.legendTitle,
|
|
position: this.legendPosition
|
|
};
|
|
}
|
|
onActivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
hasNoOptionalMarginsSet() {
|
|
return !this.margins || this.margins.length <= 0;
|
|
}
|
|
}
|
|
PieChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieChartComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
PieChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieChartComponent, selector: "ngx-charts-pie-chart", inputs: { labels: "labels", legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", explodeSlices: "explodeSlices", doughnut: "doughnut", arcWidth: "arcWidth", gradient: "gradient", activeEntries: "activeEntries", tooltipDisabled: "tooltipDisabled", labelFormatting: "labelFormatting", trimLabels: "trimLabels", maxLabelLength: "maxLabelLength", tooltipText: "tooltipText", margins: "margins" }, outputs: { dblclick: "dblclick", select: "select", activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="translation" class="pie-chart chart">
|
|
<svg:g
|
|
ngx-charts-pie-series
|
|
[colors]="colors"
|
|
[series]="data"
|
|
[showLabels]="labels"
|
|
[labelFormatting]="labelFormatting"
|
|
[trimLabels]="trimLabels"
|
|
[maxLabelLength]="maxLabelLength"
|
|
[activeEntries]="activeEntries"
|
|
[innerRadius]="innerRadius"
|
|
[outerRadius]="outerRadius"
|
|
[explodeSlices]="explodeSlices"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipText]="tooltipText"
|
|
(dblclick)="dblclick.emit($event)"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".pie-label{font-size:11px}.pie-label.animation{animation:.75s ease-in fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.pie-label-line{stroke-dasharray:100%}.pie-label-line.animation{animation:3s linear drawOut;transition:d .75s}@keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: PieSeriesComponent, selector: "g[ngx-charts-pie-series]", inputs: ["colors", "series", "dims", "innerRadius", "outerRadius", "explodeSlices", "showLabels", "gradient", "activeEntries", "labelFormatting", "trimLabels", "maxLabelLength", "tooltipText", "tooltipDisabled", "tooltipTemplate", "animations"], outputs: ["select", "activate", "deactivate", "dblclick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieChartComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-pie-chart', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelActivate)="onActivate($event, true)"
|
|
(legendLabelDeactivate)="onDeactivate($event, true)"
|
|
(legendLabelClick)="onClick($event)"
|
|
>
|
|
<svg:g [attr.transform]="translation" class="pie-chart chart">
|
|
<svg:g
|
|
ngx-charts-pie-series
|
|
[colors]="colors"
|
|
[series]="data"
|
|
[showLabels]="labels"
|
|
[labelFormatting]="labelFormatting"
|
|
[trimLabels]="trimLabels"
|
|
[maxLabelLength]="maxLabelLength"
|
|
[activeEntries]="activeEntries"
|
|
[innerRadius]="innerRadius"
|
|
[outerRadius]="outerRadius"
|
|
[explodeSlices]="explodeSlices"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipText]="tooltipText"
|
|
(dblclick)="dblclick.emit($event)"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".pie-label{font-size:11px}.pie-label.animation{animation:.75s ease-in fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.pie-label-line{stroke-dasharray:100%}.pie-label-line.animation{animation:3s linear drawOut;transition:d .75s}@keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}\n"] }]
|
|
}], propDecorators: { labels: [{
|
|
type: Input
|
|
}], legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], explodeSlices: [{
|
|
type: Input
|
|
}], doughnut: [{
|
|
type: Input
|
|
}], arcWidth: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], trimLabels: [{
|
|
type: Input
|
|
}], maxLabelLength: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], dblclick: [{
|
|
type: Output
|
|
}], margins: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
function gridSize(dims, len, minWidth) {
|
|
let rows = 1;
|
|
let cols = len;
|
|
const width = dims.width;
|
|
if (width > minWidth) {
|
|
while (width / cols < minWidth) {
|
|
rows += 1;
|
|
cols = Math.ceil(len / rows);
|
|
}
|
|
}
|
|
return [cols, rows];
|
|
}
|
|
function gridLayout(dims, data, minWidth, designatedTotal) {
|
|
const xScale = scaleBand();
|
|
const yScale = scaleBand();
|
|
const width = dims.width;
|
|
const height = dims.height;
|
|
const [columns, rows] = gridSize(dims, data.length, minWidth);
|
|
const xDomain = [];
|
|
const yDomain = [];
|
|
for (let i = 0; i < rows; i++) {
|
|
yDomain.push(i);
|
|
}
|
|
for (let i = 0; i < columns; i++) {
|
|
xDomain.push(i);
|
|
}
|
|
xScale.domain(xDomain);
|
|
yScale.domain(yDomain);
|
|
xScale.rangeRound([0, width], 0.1);
|
|
yScale.rangeRound([0, height], 0.1);
|
|
const res = [];
|
|
const total = designatedTotal ? designatedTotal : getTotal(data);
|
|
const cardWidth = xScale.bandwidth();
|
|
const cardHeight = yScale.bandwidth();
|
|
for (let i = 0; i < data.length; i++) {
|
|
res[i] = {};
|
|
res[i].data = {
|
|
name: data[i] ? data[i].name : '',
|
|
value: data[i] ? data[i].value : undefined,
|
|
extra: data[i] ? data[i].extra : undefined,
|
|
label: data[i] ? data[i].label : ''
|
|
};
|
|
res[i].x = xScale(i % columns);
|
|
res[i].y = yScale(Math.floor(i / columns));
|
|
res[i].width = cardWidth;
|
|
res[i].height = cardHeight;
|
|
res[i].data.percent = total > 0 ? res[i].data.value / total : 0;
|
|
res[i].data.total = total;
|
|
}
|
|
return res;
|
|
}
|
|
function getTotal(results) {
|
|
return results.map(d => (d ? d.value : 0)).reduce((sum, val) => sum + val, 0);
|
|
}
|
|
|
|
class PieGridSeriesComponent {
|
|
constructor(element) {
|
|
this.innerRadius = 70;
|
|
this.outerRadius = 80;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.layout = pie()
|
|
.value(d => d.data.value)
|
|
.sort(null);
|
|
this.arcs = this.getArcs();
|
|
}
|
|
getArcs() {
|
|
return this.layout(this.data).map((arc, index) => {
|
|
const label = arc.data.data.name;
|
|
const other = arc.data.data.other;
|
|
if (index === 0) {
|
|
arc.startAngle = 0;
|
|
}
|
|
const color = this.colors(label);
|
|
return {
|
|
data: arc.data.data,
|
|
class: 'arc ' + 'arc' + index,
|
|
fill: color,
|
|
startAngle: other ? 0 : arc.startAngle,
|
|
endAngle: arc.endAngle,
|
|
animate: this.animations && !other,
|
|
pointerEvents: !other
|
|
};
|
|
});
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(this.data[0].data);
|
|
}
|
|
trackBy(index, item) {
|
|
return item.data.name;
|
|
}
|
|
label(arc) {
|
|
return arc.data.name;
|
|
}
|
|
color(arc) {
|
|
return this.colors(this.label(arc));
|
|
}
|
|
}
|
|
PieGridSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieGridSeriesComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
PieGridSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieGridSeriesComponent, selector: "g[ngx-charts-pie-grid-series]", inputs: { colors: "colors", data: "data", innerRadius: "innerRadius", outerRadius: "outerRadius", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g class="pie-grid-arcs">
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
*ngFor="let arc of arcs; trackBy: trackBy"
|
|
[attr.class]="arc.class"
|
|
[startAngle]="arc.startAngle"
|
|
[endAngle]="arc.endAngle"
|
|
[innerRadius]="innerRadius"
|
|
[outerRadius]="outerRadius"
|
|
[fill]="color(arc)"
|
|
[value]="arc.data.value"
|
|
[data]="arc.data"
|
|
[gradient]="false"
|
|
[pointerEvents]="arc.pointerEvents"
|
|
[animate]="arc.animate"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: PieArcComponent, selector: "g[ngx-charts-pie-arc]", inputs: ["fill", "startAngle", "endAngle", "innerRadius", "outerRadius", "cornerRadius", "value", "max", "data", "explodeSlices", "gradient", "animate", "pointerEvents", "isActive"], outputs: ["select", "activate", "deactivate", "dblclick"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieGridSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-pie-grid-series]',
|
|
template: `
|
|
<svg:g class="pie-grid-arcs">
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
*ngFor="let arc of arcs; trackBy: trackBy"
|
|
[attr.class]="arc.class"
|
|
[startAngle]="arc.startAngle"
|
|
[endAngle]="arc.endAngle"
|
|
[innerRadius]="innerRadius"
|
|
[outerRadius]="outerRadius"
|
|
[fill]="color(arc)"
|
|
[value]="arc.data.value"
|
|
[data]="arc.data"
|
|
[gradient]="false"
|
|
[pointerEvents]="arc.pointerEvents"
|
|
[animate]="arc.animate"
|
|
(select)="onClick($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { colors: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], innerRadius: [{
|
|
type: Input
|
|
}], outerRadius: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class PieGridComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.tooltipDisabled = false;
|
|
this.label = 'Total';
|
|
this.minWidth = 150;
|
|
this.activeEntries = [];
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [20, 20, 20, 20];
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin
|
|
});
|
|
this.formatDates();
|
|
this.domain = this.getDomain();
|
|
this.data = gridLayout(this.dims, this.results, this.minWidth, this.designatedTotal);
|
|
this.transform = `translate(${this.margin[3]} , ${this.margin[0]})`;
|
|
this.series = this.getSeries();
|
|
this.setColors();
|
|
this.tooltipText = this.tooltipText || this.defaultTooltipText;
|
|
}
|
|
defaultTooltipText({ data }) {
|
|
const label = trimLabel(formatLabel(data.name));
|
|
const val = data.value.toLocaleString();
|
|
return `
|
|
<span class="tooltip-label">${label}</span>
|
|
<span class="tooltip-val">${val}</span>
|
|
`;
|
|
}
|
|
getDomain() {
|
|
return this.results.map(d => d.label);
|
|
}
|
|
getSeries() {
|
|
const total = this.designatedTotal ? this.designatedTotal : this.getTotal();
|
|
return this.data.map(d => {
|
|
const baselineLabelHeight = 20;
|
|
const padding = 10;
|
|
const name = d.data.name;
|
|
const label = formatLabel(name);
|
|
const value = d.data.value;
|
|
const radius = min([d.width - padding, d.height - baselineLabelHeight]) / 2 - 5;
|
|
const innerRadius = radius * 0.9;
|
|
let count = 0;
|
|
const colors = () => {
|
|
count += 1;
|
|
if (count === 1) {
|
|
return 'rgba(100,100,100,0.3)';
|
|
}
|
|
else {
|
|
return this.colorScale.getColor(label);
|
|
}
|
|
};
|
|
const xPos = d.x + (d.width - padding) / 2;
|
|
const yPos = d.y + (d.height - baselineLabelHeight) / 2;
|
|
return {
|
|
transform: `translate(${xPos}, ${yPos})`,
|
|
colors,
|
|
innerRadius,
|
|
outerRadius: radius,
|
|
name,
|
|
label: trimLabel(label),
|
|
total: value,
|
|
value,
|
|
percent: format('.1%')(d.data.percent),
|
|
data: [
|
|
d,
|
|
{
|
|
data: {
|
|
other: true,
|
|
value: total - value,
|
|
name: d.data.name
|
|
}
|
|
}
|
|
]
|
|
};
|
|
});
|
|
}
|
|
getTotal() {
|
|
return this.results.map(d => d.value).reduce((sum, d) => sum + d, 0);
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colorScale = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
|
}
|
|
onActivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item, fromLegend = false) {
|
|
item = this.results.find(d => {
|
|
if (fromLegend) {
|
|
return d.label === item.name;
|
|
}
|
|
else {
|
|
return d.name === item.name;
|
|
}
|
|
});
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value && d.series === item.series;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
}
|
|
PieGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieGridComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
PieGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieGridComponent, selector: "ngx-charts-pie-grid", inputs: { designatedTotal: "designatedTotal", tooltipDisabled: "tooltipDisabled", tooltipText: "tooltipText", label: "label", minWidth: "minWidth", activeEntries: "activeEntries" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="pie-grid chart">
|
|
<svg:g *ngFor="let series of series" class="pie-grid-item" [attr.transform]="series.transform">
|
|
<svg:g
|
|
ngx-charts-pie-grid-series
|
|
[colors]="series.colors"
|
|
[data]="series.data"
|
|
[innerRadius]="series.innerRadius"
|
|
[outerRadius]="series.outerRadius"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText({ data: series })"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="series.data[0].data"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
<svg:text
|
|
*ngIf="animations"
|
|
class="label percent-label"
|
|
dy="-0.5em"
|
|
x="0"
|
|
y="5"
|
|
ngx-charts-count-up
|
|
[countTo]="series.percent"
|
|
[countSuffix]="'%'"
|
|
text-anchor="middle"
|
|
></svg:text>
|
|
<svg:text *ngIf="!animations" class="label percent-label" dy="-0.5em" x="0" y="5" text-anchor="middle">
|
|
{{ series.percent.toLocaleString() }}
|
|
</svg:text>
|
|
<svg:text class="label" dy="0.5em" x="0" y="5" text-anchor="middle">
|
|
{{ series.label }}
|
|
</svg:text>
|
|
<svg:text
|
|
*ngIf="animations"
|
|
class="label"
|
|
dy="1.23em"
|
|
x="0"
|
|
[attr.y]="series.outerRadius"
|
|
text-anchor="middle"
|
|
ngx-charts-count-up
|
|
[countTo]="series.total"
|
|
[countPrefix]="label + ': '"
|
|
></svg:text>
|
|
<svg:text
|
|
*ngIf="!animations"
|
|
class="label"
|
|
dy="1.23em"
|
|
x="0"
|
|
[attr.y]="series.outerRadius"
|
|
text-anchor="middle"
|
|
>
|
|
{{ label }}: {{ series.total.toLocaleString() }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".pie-grid .arc1{opacity:.4}.pie-grid .percent-label{font-size:16px;font-weight:400}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: PieGridSeriesComponent, selector: "g[ngx-charts-pie-grid-series]", inputs: ["colors", "data", "innerRadius", "outerRadius", "animations"], outputs: ["select", "activate", "deactivate"] }, { type: CountUpDirective, selector: "[ngx-charts-count-up]", inputs: ["countDuration", "countPrefix", "countSuffix", "valueFormatting", "countDecimals", "countTo", "countFrom"], outputs: ["countChange", "countFinish"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieGridComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-pie-grid', template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="pie-grid chart">
|
|
<svg:g *ngFor="let series of series" class="pie-grid-item" [attr.transform]="series.transform">
|
|
<svg:g
|
|
ngx-charts-pie-grid-series
|
|
[colors]="series.colors"
|
|
[data]="series.data"
|
|
[innerRadius]="series.innerRadius"
|
|
[outerRadius]="series.outerRadius"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText({ data: series })"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="series.data[0].data"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
/>
|
|
<svg:text
|
|
*ngIf="animations"
|
|
class="label percent-label"
|
|
dy="-0.5em"
|
|
x="0"
|
|
y="5"
|
|
ngx-charts-count-up
|
|
[countTo]="series.percent"
|
|
[countSuffix]="'%'"
|
|
text-anchor="middle"
|
|
></svg:text>
|
|
<svg:text *ngIf="!animations" class="label percent-label" dy="-0.5em" x="0" y="5" text-anchor="middle">
|
|
{{ series.percent.toLocaleString() }}
|
|
</svg:text>
|
|
<svg:text class="label" dy="0.5em" x="0" y="5" text-anchor="middle">
|
|
{{ series.label }}
|
|
</svg:text>
|
|
<svg:text
|
|
*ngIf="animations"
|
|
class="label"
|
|
dy="1.23em"
|
|
x="0"
|
|
[attr.y]="series.outerRadius"
|
|
text-anchor="middle"
|
|
ngx-charts-count-up
|
|
[countTo]="series.total"
|
|
[countPrefix]="label + ': '"
|
|
></svg:text>
|
|
<svg:text
|
|
*ngIf="!animations"
|
|
class="label"
|
|
dy="1.23em"
|
|
x="0"
|
|
[attr.y]="series.outerRadius"
|
|
text-anchor="middle"
|
|
>
|
|
{{ label }}: {{ series.total.toLocaleString() }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".pie-grid .arc1{opacity:.4}.pie-grid .percent-label{font-size:16px;font-weight:400}\n"] }]
|
|
}], propDecorators: { designatedTotal: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipText: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], minWidth: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class PieChartModule {
|
|
}
|
|
PieChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
PieChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieChartModule, declarations: [AdvancedPieChartComponent,
|
|
PieLabelComponent,
|
|
PieArcComponent,
|
|
PieChartComponent,
|
|
PieGridComponent,
|
|
PieGridSeriesComponent,
|
|
PieSeriesComponent], imports: [ChartCommonModule], exports: [AdvancedPieChartComponent,
|
|
PieLabelComponent,
|
|
PieArcComponent,
|
|
PieChartComponent,
|
|
PieGridComponent,
|
|
PieGridSeriesComponent,
|
|
PieSeriesComponent] });
|
|
PieChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieChartModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [
|
|
AdvancedPieChartComponent,
|
|
PieLabelComponent,
|
|
PieArcComponent,
|
|
PieChartComponent,
|
|
PieGridComponent,
|
|
PieGridSeriesComponent,
|
|
PieSeriesComponent
|
|
],
|
|
exports: [
|
|
AdvancedPieChartComponent,
|
|
PieLabelComponent,
|
|
PieArcComponent,
|
|
PieChartComponent,
|
|
PieGridComponent,
|
|
PieGridSeriesComponent,
|
|
PieSeriesComponent
|
|
]
|
|
}]
|
|
}] });
|
|
|
|
class PolarChartModule {
|
|
}
|
|
PolarChartModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarChartModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
PolarChartModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarChartModule, declarations: [PolarChartComponent, PolarSeriesComponent], imports: [ChartCommonModule, PieChartModule, LineChartModule], exports: [PolarChartComponent, PolarSeriesComponent] });
|
|
PolarChartModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarChartModule, imports: [[ChartCommonModule, PieChartModule, LineChartModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PolarChartModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule, PieChartModule, LineChartModule],
|
|
declarations: [PolarChartComponent, PolarSeriesComponent],
|
|
exports: [PolarChartComponent, PolarSeriesComponent]
|
|
}]
|
|
}] });
|
|
|
|
function calculateTextWidth(fontFamilyKey, text, defaultWidth = 8) {
|
|
return text.split('').reduce((acc, curr) => {
|
|
const width = fontFamilyKey[curr] || defaultWidth;
|
|
return acc + width;
|
|
}, 0);
|
|
}
|
|
|
|
const VERDANA_FONT_WIDTHS_16_PX = {
|
|
'0': 10,
|
|
'1': 10,
|
|
'2': 10,
|
|
'3': 10,
|
|
'4': 10,
|
|
'5': 10,
|
|
'6': 10,
|
|
'7': 10,
|
|
'8': 10,
|
|
'9': 10,
|
|
A: 11,
|
|
B: 11,
|
|
C: 11,
|
|
D: 12,
|
|
E: 10,
|
|
F: 9,
|
|
G: 12,
|
|
H: 12,
|
|
I: 7,
|
|
J: 7,
|
|
K: 11,
|
|
L: 9,
|
|
M: 13,
|
|
N: 12,
|
|
O: 13,
|
|
P: 10,
|
|
Q: 13,
|
|
R: 11,
|
|
S: 11,
|
|
T: 10,
|
|
U: 12,
|
|
V: 11,
|
|
W: 16,
|
|
X: 11,
|
|
Y: 10,
|
|
Z: 11,
|
|
a: 10,
|
|
b: 10,
|
|
c: 8,
|
|
d: 10,
|
|
e: 10,
|
|
f: 6,
|
|
g: 10,
|
|
h: 10,
|
|
i: 4,
|
|
j: 6,
|
|
k: 9,
|
|
l: 4,
|
|
m: 16,
|
|
n: 10,
|
|
o: 10,
|
|
p: 10,
|
|
q: 10,
|
|
r: 7,
|
|
s: 8,
|
|
t: 6,
|
|
u: 10,
|
|
v: 9,
|
|
w: 13,
|
|
x: 9,
|
|
y: 9,
|
|
z: 8,
|
|
'!': 6,
|
|
'@': 16,
|
|
'#': 13,
|
|
$: 10,
|
|
'%': 17,
|
|
'^': 13,
|
|
'&': 12,
|
|
'*': 10,
|
|
'(': 7,
|
|
')': 7,
|
|
_: 10,
|
|
'-': 7,
|
|
'+': 13,
|
|
'=': 13,
|
|
',': 6,
|
|
'.': 6,
|
|
'/': 7,
|
|
"'": 4,
|
|
':': 7,
|
|
'|': 7,
|
|
'?': 9,
|
|
';': 7,
|
|
'<': 13,
|
|
'>': 13
|
|
};
|
|
|
|
class CardComponent {
|
|
constructor(element, cd, zone, platformId) {
|
|
this.cd = cd;
|
|
this.zone = zone;
|
|
this.platformId = platformId;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.value = '';
|
|
this.textFontSize = 12;
|
|
this.textTransform = '';
|
|
this.initialized = false;
|
|
this.bandHeight = 10;
|
|
this.textPadding = [10, 20, 5, 20];
|
|
this.labelFontSize = 15;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
ngOnInit() {
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.scaleTextSSR();
|
|
}
|
|
}
|
|
ngOnDestroy() {
|
|
if (isPlatformBrowser(this.platformId)) {
|
|
cancelAnimationFrame(this.animationReq);
|
|
}
|
|
}
|
|
update() {
|
|
this.zone.run(() => {
|
|
const hasValue = this.data && typeof this.data.value !== 'undefined';
|
|
const valueFormatting = this.valueFormatting || (card => card.value.toLocaleString());
|
|
const labelFormatting = this.labelFormatting || (card => escapeLabel(trimLabel(card.label, 55)));
|
|
this.transform = `translate(${this.x} , ${this.y})`;
|
|
this.textWidth = Math.max(0, this.width) - this.textPadding[1] - this.textPadding[3];
|
|
this.cardWidth = Math.max(0, this.width);
|
|
this.cardHeight = Math.max(0, this.height);
|
|
this.label = this.label ? this.label : this.data.name;
|
|
const cardData = {
|
|
label: this.label,
|
|
data: this.data,
|
|
value: this.data.value
|
|
};
|
|
this.formattedLabel = labelFormatting(cardData);
|
|
this.transformBand = `translate(0 , ${this.cardHeight - this.bandHeight})`;
|
|
const value = hasValue ? valueFormatting(cardData) : '';
|
|
this.value = this.paddedValue(value);
|
|
this.setPadding();
|
|
this.bandPath = roundedRect(0, 0, this.cardWidth, this.bandHeight, 3, [false, false, true, true]);
|
|
setTimeout(() => {
|
|
if (isPlatformBrowser(this.platformId)) {
|
|
this.scaleText();
|
|
}
|
|
this.value = value;
|
|
if (hasValue && !this.initialized) {
|
|
setTimeout(() => this.startCount(), 20);
|
|
}
|
|
}, 8);
|
|
});
|
|
}
|
|
paddedValue(value) {
|
|
if (this.medianSize && this.medianSize > value.length) {
|
|
value += '\u2007'.repeat(this.medianSize - value.length);
|
|
}
|
|
return value;
|
|
}
|
|
startCount() {
|
|
if (!this.initialized && this.animations) {
|
|
cancelAnimationFrame(this.animationReq);
|
|
const val = this.data.value;
|
|
const decs = decimalChecker(val);
|
|
const valueFormatting = this.valueFormatting || (card => card.value.toLocaleString());
|
|
const callback = ({ value, finished }) => {
|
|
this.zone.run(() => {
|
|
value = finished ? val : value;
|
|
this.value = valueFormatting({ label: this.label, data: this.data, value });
|
|
if (!finished) {
|
|
this.value = this.paddedValue(this.value);
|
|
}
|
|
this.cd.markForCheck();
|
|
});
|
|
};
|
|
this.animationReq = count(0, val, decs, 1, callback);
|
|
this.initialized = true;
|
|
}
|
|
}
|
|
scaleText() {
|
|
this.zone.run(() => {
|
|
const { width, height } = this.textEl.nativeElement.getBoundingClientRect();
|
|
if (width === 0 || height === 0) {
|
|
return;
|
|
}
|
|
const textPadding = (this.textPadding[1] = this.textPadding[3] = this.cardWidth / 8);
|
|
const availableWidth = this.cardWidth - 2 * textPadding;
|
|
const availableHeight = this.cardHeight / 3;
|
|
const resizeScale = Math.min(availableWidth / width, availableHeight / height);
|
|
this.textFontSize = Math.floor(this.textFontSize * resizeScale);
|
|
this.labelFontSize = Math.min(this.textFontSize, 15);
|
|
this.setPadding();
|
|
this.cd.markForCheck();
|
|
});
|
|
}
|
|
scaleTextSSR() {
|
|
const width = calculateTextWidth(VERDANA_FONT_WIDTHS_16_PX, this.value, 10);
|
|
const height = 18;
|
|
const textPadding = (this.textPadding[1] = this.textPadding[3] = this.cardWidth / 8);
|
|
const availableWidth = this.cardWidth - 2 * textPadding;
|
|
const availableHeight = this.cardHeight / 3;
|
|
const resizeScale = Math.min(availableWidth / width, availableHeight / height);
|
|
this.textFontSize = Math.floor(this.textFontSize * resizeScale);
|
|
this.labelFontSize = Math.min(this.textFontSize, 15);
|
|
this.setPadding();
|
|
}
|
|
setPadding() {
|
|
this.textPadding[1] = this.textPadding[3] = this.cardWidth / 8;
|
|
const padding = this.cardHeight / 2;
|
|
this.textPadding[0] = padding - this.textFontSize - this.labelFontSize / 2;
|
|
this.textPadding[2] = padding - this.labelFontSize;
|
|
}
|
|
onClick() {
|
|
this.select.emit(this.data);
|
|
}
|
|
}
|
|
CardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CardComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
CardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: CardComponent, selector: "g[ngx-charts-card]", inputs: { color: "color", bandColor: "bandColor", textColor: "textColor", x: "x", y: "y", width: "width", height: "height", label: "label", data: "data", medianSize: "medianSize", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", animations: "animations" }, outputs: { select: "select" }, viewQueries: [{ propertyName: "textEl", first: true, predicate: ["textEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g [attr.transform]="transform" class="cell" (click)="onClick()">
|
|
<svg:rect class="card" [style.fill]="color" [attr.width]="cardWidth" [attr.height]="cardHeight" rx="3" ry="3" />
|
|
<svg:path
|
|
*ngIf="bandColor && bandColor !== color"
|
|
class="card-band"
|
|
[attr.fill]="bandColor"
|
|
[attr.transform]="transformBand"
|
|
stroke="none"
|
|
[attr.d]="bandPath"
|
|
/>
|
|
<title>{{ label }}</title>
|
|
<svg:foreignObject
|
|
class="trimmed-label"
|
|
x="5"
|
|
[attr.x]="textPadding[3]"
|
|
[attr.y]="cardHeight - textPadding[2]"
|
|
[attr.width]="textWidth"
|
|
[attr.height]="labelFontSize + textPadding[2]"
|
|
alignment-baseline="hanging"
|
|
>
|
|
<xhtml:p
|
|
[style.color]="textColor"
|
|
[style.fontSize.px]="labelFontSize"
|
|
[style.lineHeight.px]="labelFontSize"
|
|
[innerHTML]="formattedLabel"
|
|
>
|
|
</xhtml:p>
|
|
</svg:foreignObject>
|
|
<svg:text
|
|
#textEl
|
|
class="value-text"
|
|
[attr.x]="textPadding[3]"
|
|
[attr.y]="textPadding[0]"
|
|
[style.fill]="textColor"
|
|
text-anchor="start"
|
|
alignment-baseline="hanging"
|
|
[style.font-size.pt]="textFontSize"
|
|
>
|
|
{{ value }}
|
|
</svg:text>
|
|
</svg:g>
|
|
`, isInline: true, directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CardComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-card]',
|
|
template: `
|
|
<svg:g [attr.transform]="transform" class="cell" (click)="onClick()">
|
|
<svg:rect class="card" [style.fill]="color" [attr.width]="cardWidth" [attr.height]="cardHeight" rx="3" ry="3" />
|
|
<svg:path
|
|
*ngIf="bandColor && bandColor !== color"
|
|
class="card-band"
|
|
[attr.fill]="bandColor"
|
|
[attr.transform]="transformBand"
|
|
stroke="none"
|
|
[attr.d]="bandPath"
|
|
/>
|
|
<title>{{ label }}</title>
|
|
<svg:foreignObject
|
|
class="trimmed-label"
|
|
x="5"
|
|
[attr.x]="textPadding[3]"
|
|
[attr.y]="cardHeight - textPadding[2]"
|
|
[attr.width]="textWidth"
|
|
[attr.height]="labelFontSize + textPadding[2]"
|
|
alignment-baseline="hanging"
|
|
>
|
|
<xhtml:p
|
|
[style.color]="textColor"
|
|
[style.fontSize.px]="labelFontSize"
|
|
[style.lineHeight.px]="labelFontSize"
|
|
[innerHTML]="formattedLabel"
|
|
>
|
|
</xhtml:p>
|
|
</svg:foreignObject>
|
|
<svg:text
|
|
#textEl
|
|
class="value-text"
|
|
[attr.x]="textPadding[3]"
|
|
[attr.y]="textPadding[0]"
|
|
[style.fill]="textColor"
|
|
text-anchor="start"
|
|
alignment-baseline="hanging"
|
|
[style.font-size.pt]="textFontSize"
|
|
>
|
|
{{ value }}
|
|
</svg:text>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [PLATFORM_ID]
|
|
}] }]; }, propDecorators: { color: [{
|
|
type: Input
|
|
}], bandColor: [{
|
|
type: Input
|
|
}], textColor: [{
|
|
type: Input
|
|
}], x: [{
|
|
type: Input
|
|
}], y: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], data: [{
|
|
type: Input
|
|
}], medianSize: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], textEl: [{
|
|
type: ViewChild,
|
|
args: ['textEl', { static: false }]
|
|
}] } });
|
|
|
|
/**
|
|
* Converts a hex to RGB
|
|
*
|
|
* @export
|
|
*/
|
|
function hexToRgb(value) {
|
|
// deprecated, use d3.color()
|
|
return d3_color.rgb(value);
|
|
}
|
|
/**
|
|
* Accepts a color (string) and returns a inverted hex color (string)
|
|
* http://stackoverflow.com/questions/9600295/automatically-change-text-color-to-assure-readability
|
|
*
|
|
* @export
|
|
*/
|
|
function invertColor(value) {
|
|
const color = d3_color.rgb(value);
|
|
const { r, g, b, opacity } = color;
|
|
if (opacity === 0) {
|
|
return color.toString();
|
|
}
|
|
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
|
const depth = yiq >= 128 ? -0.8 : 0.8;
|
|
return shadeRGBColor(color, depth);
|
|
}
|
|
/**
|
|
* Given a rgb, it will darken/lighten
|
|
* http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
|
|
*
|
|
* @export
|
|
* @param \{ r, g, b }
|
|
*/
|
|
function shadeRGBColor({ r, g, b }, percent) {
|
|
const t = percent < 0 ? 0 : 255;
|
|
const p = percent < 0 ? percent * -1 : percent;
|
|
r = Math.round((t - r) * p) + r;
|
|
g = Math.round((t - g) * p) + g;
|
|
b = Math.round((t - b) * p) + b;
|
|
return `rgb(${r}, ${g}, ${b})`;
|
|
}
|
|
|
|
class CardSeriesComponent {
|
|
constructor() {
|
|
this.innerPadding = 15;
|
|
this.emptyColor = 'rgba(0, 0, 0, 0)';
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
if (this.data.length > 2) {
|
|
const valueFormatting = this.valueFormatting || (card => card.value.toLocaleString());
|
|
const sortedLengths = this.data
|
|
.map(d => {
|
|
const hasValue = d && d.data && typeof d.data.value !== 'undefined' && d.data.value !== null;
|
|
return hasValue
|
|
? valueFormatting({
|
|
data: d.data,
|
|
label: d ? d.data.name : '',
|
|
value: d && d.data ? d.data.value : ''
|
|
}).length
|
|
: 0;
|
|
})
|
|
.sort((a, b) => b - a);
|
|
const idx = Math.ceil(this.data.length / 2);
|
|
this.medianSize = sortedLengths[idx];
|
|
}
|
|
const cards = this.getCards();
|
|
this.cards = cards.filter(d => d.data.value !== null);
|
|
this.emptySlots = cards.filter(d => d.data.value === null);
|
|
}
|
|
getCards() {
|
|
const yPadding = typeof this.innerPadding === 'number' ? this.innerPadding : this.innerPadding[0] + this.innerPadding[2];
|
|
const xPadding = typeof this.innerPadding === 'number' ? this.innerPadding : this.innerPadding[1] + this.innerPadding[3];
|
|
return this.data.map((d, index) => {
|
|
let label = d.data.name;
|
|
if (label && label.constructor.name === 'Date') {
|
|
label = label.toLocaleDateString();
|
|
}
|
|
else {
|
|
label = label ? label.toLocaleString() : label;
|
|
}
|
|
const value = d.data.value;
|
|
const valueColor = label ? this.colors.getColor(label) : this.emptyColor;
|
|
const color = this.cardColor || valueColor || '#000';
|
|
return {
|
|
x: d.x,
|
|
y: d.y,
|
|
width: d.width - xPadding,
|
|
height: d.height - yPadding,
|
|
color,
|
|
bandColor: this.bandColor || valueColor,
|
|
textColor: this.textColor || invertColor(color),
|
|
label,
|
|
data: d.data,
|
|
tooltipText: `${label}: ${value}`
|
|
};
|
|
});
|
|
}
|
|
trackBy(index, card) {
|
|
return card.label;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
}
|
|
CardSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CardSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
CardSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: CardSeriesComponent, selector: "g[ngx-charts-card-series]", inputs: { data: "data", dims: "dims", colors: "colors", innerPadding: "innerPadding", cardColor: "cardColor", bandColor: "bandColor", emptyColor: "emptyColor", textColor: "textColor", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", animations: "animations" }, outputs: { select: "select" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:rect
|
|
*ngFor="let c of emptySlots; trackBy: trackBy"
|
|
class="card-empty"
|
|
[attr.x]="c.x"
|
|
[attr.y]="c.y"
|
|
[style.fill]="emptyColor"
|
|
[attr.width]="c.width"
|
|
[attr.height]="c.height"
|
|
rx="3"
|
|
ry="3"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-card
|
|
*ngFor="let c of cards; trackBy: trackBy"
|
|
[x]="c.x"
|
|
[y]="c.y"
|
|
[width]="c.width"
|
|
[height]="c.height"
|
|
[color]="c.color"
|
|
[bandColor]="c.bandColor"
|
|
[textColor]="c.textColor"
|
|
[data]="c.data"
|
|
[label]="c.label"
|
|
[medianSize]="medianSize"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
/>
|
|
`, isInline: true, components: [{ type: CardComponent, selector: "g[ngx-charts-card]", inputs: ["color", "bandColor", "textColor", "x", "y", "width", "height", "label", "data", "medianSize", "valueFormatting", "labelFormatting", "animations"], outputs: ["select"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: CardSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-card-series]',
|
|
template: `
|
|
<svg:rect
|
|
*ngFor="let c of emptySlots; trackBy: trackBy"
|
|
class="card-empty"
|
|
[attr.x]="c.x"
|
|
[attr.y]="c.y"
|
|
[style.fill]="emptyColor"
|
|
[attr.width]="c.width"
|
|
[attr.height]="c.height"
|
|
rx="3"
|
|
ry="3"
|
|
/>
|
|
<svg:g
|
|
ngx-charts-card
|
|
*ngFor="let c of cards; trackBy: trackBy"
|
|
[x]="c.x"
|
|
[y]="c.y"
|
|
[width]="c.width"
|
|
[height]="c.height"
|
|
[color]="c.color"
|
|
[bandColor]="c.bandColor"
|
|
[textColor]="c.textColor"
|
|
[data]="c.data"
|
|
[label]="c.label"
|
|
[medianSize]="medianSize"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
/>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { data: [{
|
|
type: Input
|
|
}], dims: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], innerPadding: [{
|
|
type: Input
|
|
}], cardColor: [{
|
|
type: Input
|
|
}], bandColor: [{
|
|
type: Input
|
|
}], emptyColor: [{
|
|
type: Input
|
|
}], textColor: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class NumberCardComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.emptyColor = 'rgba(0, 0, 0, 0)';
|
|
this.innerPadding = 15;
|
|
this.margin = [10, 10, 10, 10];
|
|
}
|
|
get clickable() {
|
|
return !!this.select.observers.length;
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin
|
|
});
|
|
this.formatDates();
|
|
this.domain = this.getDomain();
|
|
this.setColors();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
const size = gridSize(this.dims, this.results.length, 150);
|
|
const N = size[0] * size[1];
|
|
const data = this.results.slice();
|
|
while (data.length < N) {
|
|
data.push({ value: null });
|
|
}
|
|
this.data = gridLayout(this.dims, data, 150, this.designatedTotal);
|
|
}
|
|
getDomain() {
|
|
return this.results.map(d => d.label);
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
|
}
|
|
}
|
|
NumberCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NumberCardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
NumberCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: NumberCardComponent, selector: "ngx-charts-number-card", inputs: { cardColor: "cardColor", bandColor: "bandColor", emptyColor: "emptyColor", innerPadding: "innerPadding", textColor: "textColor", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", designatedTotal: "designatedTotal" }, usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="number-card chart" [class.clickable]="clickable">
|
|
<svg:g
|
|
ngx-charts-card-series
|
|
[colors]="colors"
|
|
[cardColor]="cardColor"
|
|
[bandColor]="bandColor"
|
|
[textColor]="textColor"
|
|
[emptyColor]="emptyColor"
|
|
[data]="data"
|
|
[dims]="dims"
|
|
[innerPadding]="innerPadding"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", "ngx-charts-number-card .cell .trimmed-label{font-size:12px;pointer-events:none;overflow:hidden;text-align:left;line-height:1em}ngx-charts-number-card .cell .trimmed-label p{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;width:100%;padding:0;margin:0}ngx-charts-number-card .cell .value-text{pointer-events:none}ngx-charts-number-card .number-card.clickable .cell .card,ngx-charts-number-card .number-card.clickable .cell .card-band{cursor:pointer}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: CardSeriesComponent, selector: "g[ngx-charts-card-series]", inputs: ["data", "dims", "colors", "innerPadding", "cardColor", "bandColor", "emptyColor", "textColor", "valueFormatting", "labelFormatting", "animations"], outputs: ["select"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NumberCardComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-number-card', template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="number-card chart" [class.clickable]="clickable">
|
|
<svg:g
|
|
ngx-charts-card-series
|
|
[colors]="colors"
|
|
[cardColor]="cardColor"
|
|
[bandColor]="bandColor"
|
|
[textColor]="textColor"
|
|
[emptyColor]="emptyColor"
|
|
[data]="data"
|
|
[dims]="dims"
|
|
[innerPadding]="innerPadding"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", "ngx-charts-number-card .cell .trimmed-label{font-size:12px;pointer-events:none;overflow:hidden;text-align:left;line-height:1em}ngx-charts-number-card .cell .trimmed-label p{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;width:100%;padding:0;margin:0}ngx-charts-number-card .cell .value-text{pointer-events:none}ngx-charts-number-card .number-card.clickable .cell .card,ngx-charts-number-card .number-card.clickable .cell .card-band{cursor:pointer}\n"] }]
|
|
}], propDecorators: { cardColor: [{
|
|
type: Input
|
|
}], bandColor: [{
|
|
type: Input
|
|
}], emptyColor: [{
|
|
type: Input
|
|
}], innerPadding: [{
|
|
type: Input
|
|
}], textColor: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], designatedTotal: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class NumberCardModule {
|
|
}
|
|
NumberCardModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NumberCardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
NumberCardModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NumberCardModule, declarations: [CardComponent, CardSeriesComponent, NumberCardComponent], imports: [ChartCommonModule], exports: [CardComponent, CardSeriesComponent, NumberCardComponent] });
|
|
NumberCardModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NumberCardModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NumberCardModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [CardComponent, CardSeriesComponent, NumberCardComponent],
|
|
exports: [CardComponent, CardSeriesComponent, NumberCardComponent]
|
|
}]
|
|
}] });
|
|
|
|
class TreeMapCellComponent {
|
|
constructor(element) {
|
|
this.gradient = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.initialized = false;
|
|
this.orientation = BarOrientation;
|
|
this.element = element.nativeElement;
|
|
}
|
|
ngOnChanges() {
|
|
this.update();
|
|
this.valueFormatting = this.valueFormatting || (value => value.toLocaleString());
|
|
const labelFormatting = this.labelFormatting || (cell => escapeLabel(trimLabel(cell.label, 55)));
|
|
const cellData = {
|
|
data: this.data,
|
|
label: this.label,
|
|
value: this.value
|
|
};
|
|
this.formattedValue = this.valueFormatting(cellData.value);
|
|
this.formattedLabel = labelFormatting(cellData);
|
|
this.gradientId = 'grad' + id().toString();
|
|
this.gradientUrl = `url(#${this.gradientId})`;
|
|
this.gradientStops = this.getGradientStops();
|
|
}
|
|
update() {
|
|
if (this.initialized) {
|
|
this.animateToCurrentForm();
|
|
}
|
|
else {
|
|
if (this.animations) {
|
|
this.loadAnimation();
|
|
}
|
|
this.initialized = true;
|
|
}
|
|
}
|
|
loadAnimation() {
|
|
const node = select(this.element).select('.cell');
|
|
node.attr('opacity', 0).attr('x', this.x).attr('y', this.y);
|
|
this.animateToCurrentForm();
|
|
}
|
|
getTextColor() {
|
|
return invertColor(this.fill);
|
|
}
|
|
animateToCurrentForm() {
|
|
const node = select(this.element).select('.cell');
|
|
if (this.animations) {
|
|
node
|
|
.transition()
|
|
.duration(750)
|
|
.attr('opacity', 1)
|
|
.attr('x', this.x)
|
|
.attr('y', this.y)
|
|
.attr('width', this.width)
|
|
.attr('height', this.height);
|
|
}
|
|
else {
|
|
node.attr('opacity', 1).attr('x', this.x).attr('y', this.y).attr('width', this.width).attr('height', this.height);
|
|
}
|
|
}
|
|
onClick() {
|
|
this.select.emit(this.data);
|
|
}
|
|
getGradientStops() {
|
|
return [
|
|
{
|
|
offset: 0,
|
|
color: this.fill,
|
|
opacity: 0.3
|
|
},
|
|
{
|
|
offset: 100,
|
|
color: this.fill,
|
|
opacity: 1
|
|
}
|
|
];
|
|
}
|
|
}
|
|
TreeMapCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapCellComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
TreeMapCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: TreeMapCellComponent, selector: "g[ngx-charts-tree-map-cell]", inputs: { data: "data", fill: "fill", x: "x", y: "y", width: "width", height: "height", label: "label", value: "value", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", gradient: "gradient", animations: "animations" }, outputs: { select: "select" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g>
|
|
<defs *ngIf="gradient">
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="orientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:rect
|
|
[attr.fill]="gradient ? gradientUrl : fill"
|
|
[attr.width]="width"
|
|
[attr.height]="height"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
class="cell"
|
|
(click)="onClick()"
|
|
/>
|
|
<svg:foreignObject
|
|
*ngIf="width >= 70 && height >= 35"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
[attr.width]="width"
|
|
[attr.height]="height"
|
|
class="treemap-label"
|
|
[style.pointer-events]="'none'"
|
|
>
|
|
<xhtml:p [style.color]="getTextColor()" [style.height]="height + 'px'" [style.width]="width + 'px'">
|
|
<xhtml:span class="treemap-label" [innerHTML]="formattedLabel"> </xhtml:span>
|
|
<xhtml:br />
|
|
<xhtml:span
|
|
*ngIf="animations"
|
|
class="treemap-val"
|
|
ngx-charts-count-up
|
|
[countTo]="value"
|
|
[valueFormatting]="valueFormatting"
|
|
>
|
|
</xhtml:span>
|
|
<xhtml:span *ngIf="!animations" class="treemap-val">
|
|
{{ formattedValue }}
|
|
</xhtml:span>
|
|
</xhtml:p>
|
|
</svg:foreignObject>
|
|
</svg:g>
|
|
`, isInline: true, components: [{ type: SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }, { type: CountUpDirective, selector: "[ngx-charts-count-up]", inputs: ["countDuration", "countPrefix", "countSuffix", "valueFormatting", "countDecimals", "countTo", "countFrom"], outputs: ["countChange", "countFinish"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapCellComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-tree-map-cell]',
|
|
template: `
|
|
<svg:g>
|
|
<defs *ngIf="gradient">
|
|
<svg:g
|
|
ngx-charts-svg-linear-gradient
|
|
[orientation]="orientation.Vertical"
|
|
[name]="gradientId"
|
|
[stops]="gradientStops"
|
|
/>
|
|
</defs>
|
|
<svg:rect
|
|
[attr.fill]="gradient ? gradientUrl : fill"
|
|
[attr.width]="width"
|
|
[attr.height]="height"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
class="cell"
|
|
(click)="onClick()"
|
|
/>
|
|
<svg:foreignObject
|
|
*ngIf="width >= 70 && height >= 35"
|
|
[attr.x]="x"
|
|
[attr.y]="y"
|
|
[attr.width]="width"
|
|
[attr.height]="height"
|
|
class="treemap-label"
|
|
[style.pointer-events]="'none'"
|
|
>
|
|
<xhtml:p [style.color]="getTextColor()" [style.height]="height + 'px'" [style.width]="width + 'px'">
|
|
<xhtml:span class="treemap-label" [innerHTML]="formattedLabel"> </xhtml:span>
|
|
<xhtml:br />
|
|
<xhtml:span
|
|
*ngIf="animations"
|
|
class="treemap-val"
|
|
ngx-charts-count-up
|
|
[countTo]="value"
|
|
[valueFormatting]="valueFormatting"
|
|
>
|
|
</xhtml:span>
|
|
<xhtml:span *ngIf="!animations" class="treemap-val">
|
|
{{ formattedValue }}
|
|
</xhtml:span>
|
|
</xhtml:p>
|
|
</svg:foreignObject>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { data: [{
|
|
type: Input
|
|
}], fill: [{
|
|
type: Input
|
|
}], x: [{
|
|
type: Input
|
|
}], y: [{
|
|
type: Input
|
|
}], width: [{
|
|
type: Input
|
|
}], height: [{
|
|
type: Input
|
|
}], label: [{
|
|
type: Input
|
|
}], value: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class TreeMapCellSeriesComponent {
|
|
constructor() {
|
|
this.gradient = false;
|
|
this.tooltipDisabled = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.styleTypes = StyleTypes;
|
|
this.placementTypes = PlacementTypes;
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.cells = this.getCells();
|
|
}
|
|
getCells() {
|
|
return this.data.children
|
|
.filter(d => {
|
|
return d.depth === 1;
|
|
})
|
|
.map((d, index) => {
|
|
const label = d.id;
|
|
return {
|
|
data: d.data,
|
|
x: d.x0,
|
|
y: d.y0,
|
|
width: d.x1 - d.x0,
|
|
height: d.y1 - d.y0,
|
|
fill: this.colors.getColor(label),
|
|
label,
|
|
value: d.value
|
|
};
|
|
});
|
|
}
|
|
getTooltipText({ label, value }) {
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(label)}</span>
|
|
<span class="tooltip-val">${value.toLocaleString()}</span>
|
|
`;
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
trackBy(index, item) {
|
|
return item.label;
|
|
}
|
|
}
|
|
TreeMapCellSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapCellSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
TreeMapCellSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: TreeMapCellSeriesComponent, selector: "g[ngx-charts-tree-map-cell-series]", inputs: { data: "data", dims: "dims", colors: "colors", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", gradient: "gradient", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate", animations: "animations" }, outputs: { select: "select" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-tree-map-cell
|
|
*ngFor="let c of cells; trackBy: trackBy"
|
|
[data]="c.data"
|
|
[x]="c.x"
|
|
[y]="c.y"
|
|
[width]="c.width"
|
|
[height]="c.height"
|
|
[fill]="c.fill"
|
|
[label]="c.label"
|
|
[value]="c.value"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(c)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="c.data"
|
|
></svg:g>
|
|
`, isInline: true, components: [{ type: TreeMapCellComponent, selector: "g[ngx-charts-tree-map-cell]", inputs: ["data", "fill", "x", "y", "width", "height", "label", "value", "valueFormatting", "labelFormatting", "gradient", "animations"], outputs: ["select"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapCellSeriesComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-tree-map-cell-series]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-tree-map-cell
|
|
*ngFor="let c of cells; trackBy: trackBy"
|
|
[data]="c.data"
|
|
[x]="c.x"
|
|
[y]="c.y"
|
|
[width]="c.width"
|
|
[height]="c.height"
|
|
[fill]="c.fill"
|
|
[label]="c.label"
|
|
[value]="c.value"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(c)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="c.data"
|
|
></svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { data: [{
|
|
type: Input
|
|
}], dims: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class TreeMapComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.tooltipDisabled = false;
|
|
this.gradient = false;
|
|
this.select = new EventEmitter();
|
|
this.margin = [10, 10, 10, 10];
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin
|
|
});
|
|
this.domain = this.getDomain();
|
|
this.treemap = treemap().size([this.dims.width, this.dims.height]);
|
|
const rootNode = {
|
|
name: 'root',
|
|
value: 0,
|
|
isRoot: true
|
|
};
|
|
const root = stratify()
|
|
.id(d => {
|
|
let label = d.name;
|
|
if (label.constructor.name === 'Date') {
|
|
label = label.toLocaleDateString();
|
|
}
|
|
else {
|
|
label = label.toLocaleString();
|
|
}
|
|
return label;
|
|
})
|
|
.parentId(d => (d.isRoot ? null : 'root'))([rootNode, ...this.results])
|
|
.sum(d => d.value);
|
|
this.data = this.treemap(root);
|
|
this.setColors();
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
|
}
|
|
}
|
|
TreeMapComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
TreeMapComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: TreeMapComponent, selector: "ngx-charts-tree-map", inputs: { results: "results", tooltipDisabled: "tooltipDisabled", valueFormatting: "valueFormatting", labelFormatting: "labelFormatting", gradient: "gradient" }, outputs: { select: "select" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="tree-map chart">
|
|
<svg:g
|
|
ngx-charts-tree-map-cell-series
|
|
[colors]="colors"
|
|
[data]="data"
|
|
[dims]="dims"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".tree-map .treemap-val{font-size:1.3em;padding-top:5px;display:inline-block}.tree-map .treemap-label p{display:table-cell;text-align:center;line-height:1.2em;vertical-align:middle}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: TreeMapCellSeriesComponent, selector: "g[ngx-charts-tree-map-cell-series]", inputs: ["data", "dims", "colors", "valueFormatting", "labelFormatting", "gradient", "tooltipDisabled", "tooltipTemplate", "animations"], outputs: ["select"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-tree-map', template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="tree-map chart">
|
|
<svg:g
|
|
ngx-charts-tree-map-cell-series
|
|
[colors]="colors"
|
|
[data]="data"
|
|
[dims]="dims"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[valueFormatting]="valueFormatting"
|
|
[labelFormatting]="labelFormatting"
|
|
[gradient]="gradient"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
/>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".tree-map .treemap-val{font-size:1.3em;padding-top:5px;display:inline-block}.tree-map .treemap-label p{display:table-cell;text-align:center;line-height:1.2em;vertical-align:middle}\n"] }]
|
|
}], propDecorators: { results: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class TreeMapModule {
|
|
}
|
|
TreeMapModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
TreeMapModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapModule, declarations: [TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent], imports: [ChartCommonModule], exports: [TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent] });
|
|
TreeMapModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: TreeMapModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent],
|
|
exports: [TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent]
|
|
}]
|
|
}] });
|
|
|
|
var ElementType;
|
|
(function (ElementType) {
|
|
ElementType["Value"] = "value";
|
|
ElementType["Units"] = "units";
|
|
})(ElementType || (ElementType = {}));
|
|
class LinearGaugeComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.min = 0;
|
|
this.max = 100;
|
|
this.value = 0;
|
|
this.margin = [10, 20, 10, 20];
|
|
this.valueResizeScale = 1;
|
|
this.unitsResizeScale = 1;
|
|
this.valueTextTransform = '';
|
|
this.valueTranslate = '';
|
|
this.unitsTextTransform = '';
|
|
this.unitsTranslate = '';
|
|
this.barOrientation = BarOrientation;
|
|
}
|
|
ngAfterViewInit() {
|
|
super.ngAfterViewInit();
|
|
setTimeout(() => {
|
|
this.scaleText(ElementType.Value);
|
|
this.scaleText(ElementType.Units);
|
|
});
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.hasPreviousValue = this.previousValue !== undefined;
|
|
this.max = Math.max(this.max, this.value);
|
|
this.min = Math.min(this.min, this.value);
|
|
if (this.hasPreviousValue) {
|
|
this.max = Math.max(this.max, this.previousValue);
|
|
this.min = Math.min(this.min, this.previousValue);
|
|
}
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin
|
|
});
|
|
this.valueDomain = this.getValueDomain();
|
|
this.valueScale = this.getValueScale();
|
|
this.displayValue = this.getDisplayValue();
|
|
this.setColors();
|
|
const xOffset = this.margin[3] + this.dims.width / 2;
|
|
const yOffset = this.margin[0] + this.dims.height / 2;
|
|
this.transform = `translate(${xOffset}, ${yOffset})`;
|
|
this.transformLine = `translate(${this.margin[3] + this.valueScale(this.previousValue)}, ${yOffset})`;
|
|
this.valueTranslate = `translate(0, -15)`;
|
|
this.unitsTranslate = `translate(0, 15)`;
|
|
if (isPlatformServer(this.platformId)) {
|
|
this.scaleTextSSR('value');
|
|
this.scaleTextSSR('units');
|
|
}
|
|
else {
|
|
setTimeout(() => this.scaleText(ElementType.Value), 50);
|
|
setTimeout(() => this.scaleText(ElementType.Units), 50);
|
|
}
|
|
}
|
|
getValueDomain() {
|
|
return [this.min, this.max];
|
|
}
|
|
getValueScale() {
|
|
return scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
|
}
|
|
getDisplayValue() {
|
|
if (this.valueFormatting) {
|
|
return this.valueFormatting(this.value);
|
|
}
|
|
return this.value.toLocaleString();
|
|
}
|
|
scaleText(element, repeat = true) {
|
|
let el;
|
|
let resizeScale;
|
|
if (element === ElementType.Value) {
|
|
el = this.valueTextEl;
|
|
resizeScale = this.valueResizeScale;
|
|
}
|
|
else {
|
|
el = this.unitsTextEl;
|
|
resizeScale = this.unitsResizeScale;
|
|
}
|
|
const { width, height } = el.nativeElement.getBoundingClientRect();
|
|
if (width === 0 || height === 0)
|
|
return;
|
|
const oldScale = resizeScale;
|
|
const availableWidth = this.dims.width;
|
|
const availableHeight = Math.max(this.dims.height / 2 - 15, 0);
|
|
const resizeScaleWidth = Math.floor((availableWidth / (width / resizeScale)) * 100) / 100;
|
|
const resizeScaleHeight = Math.floor((availableHeight / (height / resizeScale)) * 100) / 100;
|
|
resizeScale = Math.min(resizeScaleHeight, resizeScaleWidth);
|
|
if (resizeScale !== oldScale) {
|
|
if (element === ElementType.Value) {
|
|
this.valueResizeScale = resizeScale;
|
|
this.valueTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
|
}
|
|
else {
|
|
this.unitsResizeScale = resizeScale;
|
|
this.unitsTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
|
}
|
|
this.cd.markForCheck();
|
|
if (repeat && isPlatformBrowser(this.platformId)) {
|
|
setTimeout(() => {
|
|
this.scaleText(element, false);
|
|
}, 50);
|
|
}
|
|
}
|
|
}
|
|
scaleTextSSR(element) {
|
|
let resizeScale = 1;
|
|
const value = element === 'value' ? this.displayValue : this.units;
|
|
const width = calculateTextWidth(VERDANA_FONT_WIDTHS_16_PX, value, 10);
|
|
const height = 25;
|
|
const availableWidth = this.dims.width;
|
|
const availableHeight = Math.max(this.dims.height / 2 - 15, 0);
|
|
const resizeScaleWidth = Math.floor((availableWidth / (width / resizeScale)) * 100) / 100;
|
|
const resizeScaleHeight = Math.floor((availableHeight / (height / resizeScale)) * 100) / 100;
|
|
resizeScale = Math.min(resizeScaleHeight, resizeScaleWidth);
|
|
if (element === 'value') {
|
|
this.valueResizeScale = resizeScale;
|
|
this.valueTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
|
}
|
|
else {
|
|
this.unitsResizeScale = resizeScale;
|
|
this.unitsTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
|
}
|
|
this.cd.markForCheck();
|
|
}
|
|
onClick() {
|
|
this.select.emit({
|
|
name: 'Value',
|
|
value: this.value
|
|
});
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, [this.value], this.customColors);
|
|
}
|
|
}
|
|
LinearGaugeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LinearGaugeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
LinearGaugeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: LinearGaugeComponent, selector: "ngx-charts-linear-gauge", inputs: { min: "min", max: "max", value: "value", units: "units", previousValue: "previousValue", valueFormatting: "valueFormatting" }, viewQueries: [{ propertyName: "valueTextEl", first: true, predicate: ["valueTextEl"], descendants: true }, { propertyName: "unitsTextEl", first: true, predicate: ["unitsTextEl"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations" (click)="onClick()">
|
|
<svg:g class="linear-gauge chart">
|
|
<svg:g
|
|
ngx-charts-bar
|
|
class="background-bar"
|
|
[width]="dims.width"
|
|
[height]="3"
|
|
[x]="margin[3]"
|
|
[y]="dims.height / 2 + margin[0] - 2"
|
|
[data]="{}"
|
|
[orientation]="barOrientation.Horizontal"
|
|
[roundEdges]="true"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-bar
|
|
[width]="valueScale(value)"
|
|
[height]="3"
|
|
[x]="margin[3]"
|
|
[y]="dims.height / 2 + margin[0] - 2"
|
|
[fill]="colors.getColor(units)"
|
|
[data]="{}"
|
|
[orientation]="barOrientation.Horizontal"
|
|
[roundEdges]="true"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
|
|
<svg:line
|
|
*ngIf="hasPreviousValue"
|
|
[attr.transform]="transformLine"
|
|
x1="0"
|
|
y1="5"
|
|
x2="0"
|
|
y2="15"
|
|
[attr.stroke]="colors.getColor(units)"
|
|
/>
|
|
|
|
<svg:line
|
|
*ngIf="hasPreviousValue"
|
|
[attr.transform]="transformLine"
|
|
x1="0"
|
|
y1="-5"
|
|
x2="0"
|
|
y2="-15"
|
|
[attr.stroke]="colors.getColor(units)"
|
|
/>
|
|
|
|
<svg:g [attr.transform]="transform">
|
|
<svg:g [attr.transform]="valueTranslate">
|
|
<svg:text
|
|
#valueTextEl
|
|
class="value"
|
|
[style.textAnchor]="'middle'"
|
|
[attr.transform]="valueTextTransform"
|
|
alignment-baseline="after-edge"
|
|
>
|
|
{{ displayValue }}
|
|
</svg:text>
|
|
</svg:g>
|
|
|
|
<svg:g [attr.transform]="unitsTranslate">
|
|
<svg:text
|
|
#unitsTextEl
|
|
class="units"
|
|
[style.textAnchor]="'middle'"
|
|
[attr.transform]="unitsTextTransform"
|
|
alignment-baseline="before-edge"
|
|
>
|
|
{{ units }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".linear-gauge{cursor:pointer}.linear-gauge .background-bar path{fill:#0000000d}.linear-gauge .units{fill:#666}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: BarComponent, selector: "g[ngx-charts-bar]", inputs: ["fill", "data", "width", "height", "x", "y", "orientation", "roundEdges", "gradient", "offset", "isActive", "stops", "animations", "ariaLabel", "noBarWhenZero"], outputs: ["select", "activate", "deactivate"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: LinearGaugeComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-linear-gauge', template: `
|
|
<ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations" (click)="onClick()">
|
|
<svg:g class="linear-gauge chart">
|
|
<svg:g
|
|
ngx-charts-bar
|
|
class="background-bar"
|
|
[width]="dims.width"
|
|
[height]="3"
|
|
[x]="margin[3]"
|
|
[y]="dims.height / 2 + margin[0] - 2"
|
|
[data]="{}"
|
|
[orientation]="barOrientation.Horizontal"
|
|
[roundEdges]="true"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-bar
|
|
[width]="valueScale(value)"
|
|
[height]="3"
|
|
[x]="margin[3]"
|
|
[y]="dims.height / 2 + margin[0] - 2"
|
|
[fill]="colors.getColor(units)"
|
|
[data]="{}"
|
|
[orientation]="barOrientation.Horizontal"
|
|
[roundEdges]="true"
|
|
[animations]="animations"
|
|
></svg:g>
|
|
|
|
<svg:line
|
|
*ngIf="hasPreviousValue"
|
|
[attr.transform]="transformLine"
|
|
x1="0"
|
|
y1="5"
|
|
x2="0"
|
|
y2="15"
|
|
[attr.stroke]="colors.getColor(units)"
|
|
/>
|
|
|
|
<svg:line
|
|
*ngIf="hasPreviousValue"
|
|
[attr.transform]="transformLine"
|
|
x1="0"
|
|
y1="-5"
|
|
x2="0"
|
|
y2="-15"
|
|
[attr.stroke]="colors.getColor(units)"
|
|
/>
|
|
|
|
<svg:g [attr.transform]="transform">
|
|
<svg:g [attr.transform]="valueTranslate">
|
|
<svg:text
|
|
#valueTextEl
|
|
class="value"
|
|
[style.textAnchor]="'middle'"
|
|
[attr.transform]="valueTextTransform"
|
|
alignment-baseline="after-edge"
|
|
>
|
|
{{ displayValue }}
|
|
</svg:text>
|
|
</svg:g>
|
|
|
|
<svg:g [attr.transform]="unitsTranslate">
|
|
<svg:text
|
|
#unitsTextEl
|
|
class="units"
|
|
[style.textAnchor]="'middle'"
|
|
[attr.transform]="unitsTextTransform"
|
|
alignment-baseline="before-edge"
|
|
>
|
|
{{ units }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".linear-gauge{cursor:pointer}.linear-gauge .background-bar path{fill:#0000000d}.linear-gauge .units{fill:#666}\n"] }]
|
|
}], propDecorators: { min: [{
|
|
type: Input
|
|
}], max: [{
|
|
type: Input
|
|
}], value: [{
|
|
type: Input
|
|
}], units: [{
|
|
type: Input
|
|
}], previousValue: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], valueTextEl: [{
|
|
type: ViewChild,
|
|
args: ['valueTextEl']
|
|
}], unitsTextEl: [{
|
|
type: ViewChild,
|
|
args: ['unitsTextEl']
|
|
}] } });
|
|
|
|
class GaugeArcComponent {
|
|
constructor() {
|
|
this.isActive = false;
|
|
this.tooltipDisabled = false;
|
|
this.animations = true;
|
|
this.select = new EventEmitter();
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.placementTypes = PlacementTypes;
|
|
this.styleTypes = StyleTypes;
|
|
}
|
|
tooltipText(arc) {
|
|
const label = formatLabel(arc.data.name);
|
|
let val;
|
|
if (this.valueFormatting) {
|
|
val = this.valueFormatting(arc.data.value);
|
|
}
|
|
else {
|
|
val = formatLabel(arc.data.value);
|
|
}
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(label)}</span>
|
|
<span class="tooltip-val">${val}</span>
|
|
`;
|
|
}
|
|
}
|
|
GaugeArcComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeArcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
GaugeArcComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: GaugeArcComponent, selector: "g[ngx-charts-gauge-arc]", inputs: { backgroundArc: "backgroundArc", valueArc: "valueArc", cornerRadius: "cornerRadius", colors: "colors", isActive: "isActive", tooltipDisabled: "tooltipDisabled", valueFormatting: "valueFormatting", tooltipTemplate: "tooltipTemplate", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, ngImport: i0, template: `
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
class="background-arc"
|
|
[startAngle]="0"
|
|
[endAngle]="backgroundArc.endAngle"
|
|
[innerRadius]="backgroundArc.innerRadius"
|
|
[outerRadius]="backgroundArc.outerRadius"
|
|
[cornerRadius]="cornerRadius"
|
|
[data]="backgroundArc.data"
|
|
[animate]="false"
|
|
[pointerEvents]="false"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
[startAngle]="0"
|
|
[endAngle]="valueArc.endAngle"
|
|
[innerRadius]="valueArc.innerRadius"
|
|
[outerRadius]="valueArc.outerRadius"
|
|
[cornerRadius]="cornerRadius"
|
|
[fill]="colors.getColor(valueArc.data.name)"
|
|
[data]="valueArc.data"
|
|
[animate]="animations"
|
|
[isActive]="isActive"
|
|
(select)="select.emit($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText(valueArc)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="valueArc.data"
|
|
></svg:g>
|
|
`, isInline: true, components: [{ type: PieArcComponent, selector: "g[ngx-charts-pie-arc]", inputs: ["fill", "startAngle", "endAngle", "innerRadius", "outerRadius", "cornerRadius", "value", "max", "data", "explodeSlices", "gradient", "animate", "pointerEvents", "isActive"], outputs: ["select", "activate", "deactivate", "dblclick"] }], directives: [{ type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeArcComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-gauge-arc]',
|
|
template: `
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
class="background-arc"
|
|
[startAngle]="0"
|
|
[endAngle]="backgroundArc.endAngle"
|
|
[innerRadius]="backgroundArc.innerRadius"
|
|
[outerRadius]="backgroundArc.outerRadius"
|
|
[cornerRadius]="cornerRadius"
|
|
[data]="backgroundArc.data"
|
|
[animate]="false"
|
|
[pointerEvents]="false"
|
|
></svg:g>
|
|
<svg:g
|
|
ngx-charts-pie-arc
|
|
[startAngle]="0"
|
|
[endAngle]="valueArc.endAngle"
|
|
[innerRadius]="valueArc.innerRadius"
|
|
[outerRadius]="valueArc.outerRadius"
|
|
[cornerRadius]="cornerRadius"
|
|
[fill]="colors.getColor(valueArc.data.name)"
|
|
[data]="valueArc.data"
|
|
[animate]="animations"
|
|
[isActive]="isActive"
|
|
(select)="select.emit($event)"
|
|
(activate)="activate.emit($event)"
|
|
(deactivate)="deactivate.emit($event)"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipPlacement]="placementTypes.Top"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : tooltipText(valueArc)"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="valueArc.data"
|
|
></svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { backgroundArc: [{
|
|
type: Input
|
|
}], valueArc: [{
|
|
type: Input
|
|
}], cornerRadius: [{
|
|
type: Input
|
|
}], colors: [{
|
|
type: Input
|
|
}], isActive: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], tooltipTemplate: [{
|
|
type: Input
|
|
}], animations: [{
|
|
type: Input
|
|
}], select: [{
|
|
type: Output
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}] } });
|
|
|
|
class GaugeAxisComponent {
|
|
constructor() {
|
|
this.rotate = '';
|
|
}
|
|
ngOnChanges(changes) {
|
|
this.update();
|
|
}
|
|
update() {
|
|
this.rotationAngle = -90 + this.startAngle;
|
|
this.rotate = `rotate(${this.rotationAngle})`;
|
|
this.ticks = this.getTicks();
|
|
}
|
|
getTicks() {
|
|
const bigTickSegment = this.angleSpan / this.bigSegments;
|
|
const smallTickSegment = bigTickSegment / this.smallSegments;
|
|
const tickLength = 20;
|
|
const ticks = {
|
|
big: [],
|
|
small: []
|
|
};
|
|
const startDistance = this.radius + 10;
|
|
const textDist = startDistance + tickLength + 10;
|
|
for (let i = 0; i <= this.bigSegments; i++) {
|
|
const angleDeg = i * bigTickSegment;
|
|
const angle = (angleDeg * Math.PI) / 180;
|
|
const textAnchor = this.getTextAnchor(angleDeg);
|
|
let skip = false;
|
|
if (i === 0 && this.angleSpan === 360) {
|
|
skip = true;
|
|
}
|
|
if (!skip) {
|
|
let text = Number.parseFloat(this.valueScale.invert(angleDeg).toString()).toLocaleString();
|
|
if (this.tickFormatting) {
|
|
text = this.tickFormatting(text);
|
|
}
|
|
ticks.big.push({
|
|
line: this.getTickPath(startDistance, tickLength, angle),
|
|
textAnchor,
|
|
text,
|
|
textTransform: `
|
|
translate(${textDist * Math.cos(angle)}, ${textDist * Math.sin(angle)}) rotate(${-this.rotationAngle})
|
|
`
|
|
});
|
|
}
|
|
if (i === this.bigSegments) {
|
|
continue;
|
|
}
|
|
for (let j = 1; j <= this.smallSegments; j++) {
|
|
const smallAngleDeg = angleDeg + j * smallTickSegment;
|
|
const smallAngle = (smallAngleDeg * Math.PI) / 180;
|
|
ticks.small.push({
|
|
line: this.getTickPath(startDistance, tickLength / 2, smallAngle)
|
|
});
|
|
}
|
|
}
|
|
return ticks;
|
|
}
|
|
getTextAnchor(angle) {
|
|
// [0, 45] = 'middle';
|
|
// [46, 135] = 'start';
|
|
// [136, 225] = 'middle';
|
|
// [226, 315] = 'end';
|
|
angle = (this.startAngle + angle) % 360;
|
|
let textAnchor = TextAnchor.Middle;
|
|
if (angle > 45 && angle <= 135) {
|
|
textAnchor = TextAnchor.Start;
|
|
}
|
|
else if (angle > 225 && angle <= 315) {
|
|
textAnchor = TextAnchor.End;
|
|
}
|
|
return textAnchor;
|
|
}
|
|
getTickPath(startDistance, tickLength, angle) {
|
|
const y1 = startDistance * Math.sin(angle);
|
|
const y2 = (startDistance + tickLength) * Math.sin(angle);
|
|
const x1 = startDistance * Math.cos(angle);
|
|
const x2 = (startDistance + tickLength) * Math.cos(angle);
|
|
const points = [
|
|
{ x: x1, y: y1 },
|
|
{ x: x2, y: y2 }
|
|
];
|
|
const lineGenerator = line()
|
|
.x(d => d.x)
|
|
.y(d => d.y);
|
|
return lineGenerator(points);
|
|
}
|
|
}
|
|
GaugeAxisComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeAxisComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
GaugeAxisComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: GaugeAxisComponent, selector: "g[ngx-charts-gauge-axis]", inputs: { bigSegments: "bigSegments", smallSegments: "smallSegments", min: "min", max: "max", angleSpan: "angleSpan", startAngle: "startAngle", radius: "radius", valueScale: "valueScale", tickFormatting: "tickFormatting" }, usesOnChanges: true, ngImport: i0, template: `
|
|
<svg:g [attr.transform]="rotate">
|
|
<svg:g *ngFor="let tick of ticks.big" class="gauge-tick gauge-tick-large">
|
|
<svg:path [attr.d]="tick.line" />
|
|
</svg:g>
|
|
<svg:g *ngFor="let tick of ticks.big" class="gauge-tick gauge-tick-large">
|
|
<svg:text
|
|
[style.textAnchor]="tick.textAnchor"
|
|
[attr.transform]="tick.textTransform"
|
|
alignment-baseline="central"
|
|
>
|
|
{{ tick.text }}
|
|
</svg:text>
|
|
</svg:g>
|
|
<svg:g *ngFor="let tick of ticks.small" class="gauge-tick gauge-tick-small">
|
|
<svg:path [attr.d]="tick.line" />
|
|
</svg:g>
|
|
</svg:g>
|
|
`, isInline: true, directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeAxisComponent, decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'g[ngx-charts-gauge-axis]',
|
|
template: `
|
|
<svg:g [attr.transform]="rotate">
|
|
<svg:g *ngFor="let tick of ticks.big" class="gauge-tick gauge-tick-large">
|
|
<svg:path [attr.d]="tick.line" />
|
|
</svg:g>
|
|
<svg:g *ngFor="let tick of ticks.big" class="gauge-tick gauge-tick-large">
|
|
<svg:text
|
|
[style.textAnchor]="tick.textAnchor"
|
|
[attr.transform]="tick.textTransform"
|
|
alignment-baseline="central"
|
|
>
|
|
{{ tick.text }}
|
|
</svg:text>
|
|
</svg:g>
|
|
<svg:g *ngFor="let tick of ticks.small" class="gauge-tick gauge-tick-small">
|
|
<svg:path [attr.d]="tick.line" />
|
|
</svg:g>
|
|
</svg:g>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
}]
|
|
}], propDecorators: { bigSegments: [{
|
|
type: Input
|
|
}], smallSegments: [{
|
|
type: Input
|
|
}], min: [{
|
|
type: Input
|
|
}], max: [{
|
|
type: Input
|
|
}], angleSpan: [{
|
|
type: Input
|
|
}], startAngle: [{
|
|
type: Input
|
|
}], radius: [{
|
|
type: Input
|
|
}], valueScale: [{
|
|
type: Input
|
|
}], tickFormatting: [{
|
|
type: Input
|
|
}] } });
|
|
|
|
class GaugeComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.legend = false;
|
|
this.legendTitle = 'Legend';
|
|
this.legendPosition = LegendPosition.Right;
|
|
this.min = 0;
|
|
this.max = 100;
|
|
this.bigSegments = 10;
|
|
this.smallSegments = 5;
|
|
this.showAxis = true;
|
|
this.startAngle = -120;
|
|
this.angleSpan = 240;
|
|
this.activeEntries = [];
|
|
this.tooltipDisabled = false;
|
|
this.showText = true;
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.resizeScale = 1;
|
|
this.rotation = '';
|
|
this.textTransform = 'scale(1, 1)';
|
|
this.cornerRadius = 10;
|
|
}
|
|
ngAfterViewInit() {
|
|
super.ngAfterViewInit();
|
|
setTimeout(() => this.scaleText());
|
|
}
|
|
update() {
|
|
super.update();
|
|
if (!this.showAxis) {
|
|
if (!this.margin) {
|
|
this.margin = [10, 20, 10, 20];
|
|
}
|
|
}
|
|
else {
|
|
if (!this.margin) {
|
|
this.margin = [60, 100, 60, 100];
|
|
}
|
|
}
|
|
// make the starting angle positive
|
|
if (this.startAngle < 0) {
|
|
this.startAngle = (this.startAngle % 360) + 360;
|
|
}
|
|
this.angleSpan = Math.min(this.angleSpan, 360);
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
showLegend: this.legend,
|
|
legendPosition: this.legendPosition
|
|
});
|
|
this.domain = this.getDomain();
|
|
this.valueDomain = this.getValueDomain();
|
|
this.valueScale = this.getValueScale();
|
|
this.displayValue = this.getDisplayValue();
|
|
this.outerRadius = Math.min(this.dims.width, this.dims.height) / 2;
|
|
this.arcs = this.getArcs();
|
|
this.setColors();
|
|
this.legendOptions = this.getLegendOptions();
|
|
const xOffset = this.margin[3] + this.dims.width / 2;
|
|
const yOffset = this.margin[0] + this.dims.height / 2;
|
|
this.transform = `translate(${xOffset}, ${yOffset})`;
|
|
this.rotation = `rotate(${this.startAngle})`;
|
|
setTimeout(() => this.scaleText(), 50);
|
|
}
|
|
getArcs() {
|
|
const arcs = [];
|
|
const availableRadius = this.outerRadius * 0.7;
|
|
const radiusPerArc = Math.min(availableRadius / this.results.length, 10);
|
|
const arcWidth = radiusPerArc * 0.7;
|
|
this.textRadius = this.outerRadius - this.results.length * radiusPerArc;
|
|
this.cornerRadius = Math.floor(arcWidth / 2);
|
|
let i = 0;
|
|
for (const d of this.results) {
|
|
const outerRadius = this.outerRadius - i * radiusPerArc;
|
|
const innerRadius = outerRadius - arcWidth;
|
|
const backgroundArc = {
|
|
endAngle: (this.angleSpan * Math.PI) / 180,
|
|
innerRadius,
|
|
outerRadius,
|
|
data: {
|
|
value: this.max,
|
|
name: d.name
|
|
}
|
|
};
|
|
const valueArc = {
|
|
endAngle: (Math.min(this.valueScale(d.value), this.angleSpan) * Math.PI) / 180,
|
|
innerRadius,
|
|
outerRadius,
|
|
data: {
|
|
value: d.value,
|
|
name: d.name
|
|
}
|
|
};
|
|
const arc = {
|
|
backgroundArc,
|
|
valueArc
|
|
};
|
|
arcs.push(arc);
|
|
i++;
|
|
}
|
|
return arcs;
|
|
}
|
|
getDomain() {
|
|
return this.results.map(d => d.name);
|
|
}
|
|
getValueDomain() {
|
|
const values = this.results.map(d => d.value);
|
|
const dataMin = Math.min(...values);
|
|
const dataMax = Math.max(...values);
|
|
if (this.min !== undefined) {
|
|
this.min = Math.min(this.min, dataMin);
|
|
}
|
|
else {
|
|
this.min = dataMin;
|
|
}
|
|
if (this.max !== undefined) {
|
|
this.max = Math.max(this.max, dataMax);
|
|
}
|
|
else {
|
|
this.max = dataMax;
|
|
}
|
|
return [this.min, this.max];
|
|
}
|
|
getValueScale() {
|
|
return scaleLinear().range([0, this.angleSpan]).nice().domain(this.valueDomain);
|
|
}
|
|
getDisplayValue() {
|
|
const value = this.results.map(d => d.value).reduce((a, b) => a + b, 0);
|
|
if (this.textValue && 0 !== this.textValue.length) {
|
|
return this.textValue.toLocaleString();
|
|
}
|
|
if (this.valueFormatting) {
|
|
return this.valueFormatting(value);
|
|
}
|
|
return value.toLocaleString();
|
|
}
|
|
scaleText(repeat = true) {
|
|
if (!this.showText) {
|
|
return;
|
|
}
|
|
const { width } = this.textEl.nativeElement.getBoundingClientRect();
|
|
const oldScale = this.resizeScale;
|
|
if (width === 0) {
|
|
this.resizeScale = 1;
|
|
}
|
|
else {
|
|
const availableSpace = this.textRadius;
|
|
this.resizeScale = Math.floor((availableSpace / (width / this.resizeScale)) * 100) / 100;
|
|
}
|
|
if (this.resizeScale !== oldScale) {
|
|
this.textTransform = `scale(${this.resizeScale}, ${this.resizeScale})`;
|
|
this.cd.markForCheck();
|
|
if (repeat) {
|
|
setTimeout(() => this.scaleText(false), 50);
|
|
}
|
|
}
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
getLegendOptions() {
|
|
return {
|
|
scaleType: ScaleType.Ordinal,
|
|
colors: this.colors,
|
|
domain: this.domain,
|
|
title: this.legendTitle,
|
|
position: this.legendPosition
|
|
};
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
|
}
|
|
onActivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
if (idx > -1) {
|
|
return;
|
|
}
|
|
this.activeEntries = [item, ...this.activeEntries];
|
|
this.activate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
onDeactivate(item) {
|
|
const idx = this.activeEntries.findIndex(d => {
|
|
return d.name === item.name && d.value === item.value;
|
|
});
|
|
this.activeEntries.splice(idx, 1);
|
|
this.activeEntries = [...this.activeEntries];
|
|
this.deactivate.emit({ value: item, entries: this.activeEntries });
|
|
}
|
|
isActive(entry) {
|
|
if (!this.activeEntries)
|
|
return false;
|
|
const item = this.activeEntries.find(d => {
|
|
return entry.name === d.name && entry.series === d.series;
|
|
});
|
|
return item !== undefined;
|
|
}
|
|
trackBy(index, item) {
|
|
return item.valueArc.data.name;
|
|
}
|
|
}
|
|
GaugeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
GaugeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: GaugeComponent, selector: "ngx-charts-gauge", inputs: { legend: "legend", legendTitle: "legendTitle", legendPosition: "legendPosition", min: "min", max: "max", textValue: "textValue", units: "units", bigSegments: "bigSegments", smallSegments: "smallSegments", results: "results", showAxis: "showAxis", startAngle: "startAngle", angleSpan: "angleSpan", activeEntries: "activeEntries", axisTickFormatting: "axisTickFormatting", tooltipDisabled: "tooltipDisabled", valueFormatting: "valueFormatting", showText: "showText", margin: "margin" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], viewQueries: [{ propertyName: "textEl", first: true, predicate: ["textEl"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="gauge chart">
|
|
<svg:g *ngFor="let arc of arcs; trackBy: trackBy" [attr.transform]="rotation">
|
|
<svg:g
|
|
ngx-charts-gauge-arc
|
|
[backgroundArc]="arc.backgroundArc"
|
|
[valueArc]="arc.valueArc"
|
|
[cornerRadius]="cornerRadius"
|
|
[colors]="colors"
|
|
[isActive]="isActive(arc.valueArc.data)"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[valueFormatting]="valueFormatting"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g
|
|
ngx-charts-gauge-axis
|
|
*ngIf="showAxis"
|
|
[bigSegments]="bigSegments"
|
|
[smallSegments]="smallSegments"
|
|
[min]="min"
|
|
[max]="max"
|
|
[radius]="outerRadius"
|
|
[angleSpan]="angleSpan"
|
|
[valueScale]="valueScale"
|
|
[startAngle]="startAngle"
|
|
[tickFormatting]="axisTickFormatting"
|
|
></svg:g>
|
|
|
|
<svg:text
|
|
#textEl
|
|
*ngIf="showText"
|
|
[style.textAnchor]="'middle'"
|
|
[attr.transform]="textTransform"
|
|
alignment-baseline="central"
|
|
>
|
|
<tspan x="0" dy="0">{{ displayValue }}</tspan>
|
|
<tspan x="0" dy="1.2em">{{ units }}</tspan>
|
|
</svg:text>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".gauge .background-arc path{fill:#0000000d}.gauge .gauge-tick path{stroke:#666}.gauge .gauge-tick text{font-size:12px;fill:#666;font-weight:700}.gauge .gauge-tick-large path{stroke-width:2px}.gauge .gauge-tick-small path{stroke-width:1px}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }, { type: GaugeArcComponent, selector: "g[ngx-charts-gauge-arc]", inputs: ["backgroundArc", "valueArc", "cornerRadius", "colors", "isActive", "tooltipDisabled", "valueFormatting", "tooltipTemplate", "animations"], outputs: ["select", "activate", "deactivate"] }, { type: GaugeAxisComponent, selector: "g[ngx-charts-gauge-axis]", inputs: ["bigSegments", "smallSegments", "min", "max", "angleSpan", "startAngle", "radius", "valueScale", "tickFormatting"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-gauge', template: `
|
|
<ngx-charts-chart
|
|
[view]="[width, height]"
|
|
[showLegend]="legend"
|
|
[legendOptions]="legendOptions"
|
|
[activeEntries]="activeEntries"
|
|
[animations]="animations"
|
|
(legendLabelClick)="onClick($event)"
|
|
(legendLabelActivate)="onActivate($event)"
|
|
(legendLabelDeactivate)="onDeactivate($event)"
|
|
>
|
|
<svg:g [attr.transform]="transform" class="gauge chart">
|
|
<svg:g *ngFor="let arc of arcs; trackBy: trackBy" [attr.transform]="rotation">
|
|
<svg:g
|
|
ngx-charts-gauge-arc
|
|
[backgroundArc]="arc.backgroundArc"
|
|
[valueArc]="arc.valueArc"
|
|
[cornerRadius]="cornerRadius"
|
|
[colors]="colors"
|
|
[isActive]="isActive(arc.valueArc.data)"
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[valueFormatting]="valueFormatting"
|
|
[animations]="animations"
|
|
(select)="onClick($event)"
|
|
(activate)="onActivate($event)"
|
|
(deactivate)="onDeactivate($event)"
|
|
></svg:g>
|
|
</svg:g>
|
|
|
|
<svg:g
|
|
ngx-charts-gauge-axis
|
|
*ngIf="showAxis"
|
|
[bigSegments]="bigSegments"
|
|
[smallSegments]="smallSegments"
|
|
[min]="min"
|
|
[max]="max"
|
|
[radius]="outerRadius"
|
|
[angleSpan]="angleSpan"
|
|
[valueScale]="valueScale"
|
|
[startAngle]="startAngle"
|
|
[tickFormatting]="axisTickFormatting"
|
|
></svg:g>
|
|
|
|
<svg:text
|
|
#textEl
|
|
*ngIf="showText"
|
|
[style.textAnchor]="'middle'"
|
|
[attr.transform]="textTransform"
|
|
alignment-baseline="central"
|
|
>
|
|
<tspan x="0" dy="0">{{ displayValue }}</tspan>
|
|
<tspan x="0" dy="1.2em">{{ units }}</tspan>
|
|
</svg:text>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n", ".gauge .background-arc path{fill:#0000000d}.gauge .gauge-tick path{stroke:#666}.gauge .gauge-tick text{font-size:12px;fill:#666;font-weight:700}.gauge .gauge-tick-large path{stroke-width:2px}.gauge .gauge-tick-small path{stroke-width:1px}\n"] }]
|
|
}], propDecorators: { legend: [{
|
|
type: Input
|
|
}], legendTitle: [{
|
|
type: Input
|
|
}], legendPosition: [{
|
|
type: Input
|
|
}], min: [{
|
|
type: Input
|
|
}], max: [{
|
|
type: Input
|
|
}], textValue: [{
|
|
type: Input
|
|
}], units: [{
|
|
type: Input
|
|
}], bigSegments: [{
|
|
type: Input
|
|
}], smallSegments: [{
|
|
type: Input
|
|
}], results: [{
|
|
type: Input
|
|
}], showAxis: [{
|
|
type: Input
|
|
}], startAngle: [{
|
|
type: Input
|
|
}], angleSpan: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], axisTickFormatting: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], valueFormatting: [{
|
|
type: Input
|
|
}], showText: [{
|
|
type: Input
|
|
}], margin: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}], textEl: [{
|
|
type: ViewChild,
|
|
args: ['textEl']
|
|
}] } });
|
|
|
|
class GaugeModule {
|
|
}
|
|
GaugeModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
GaugeModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeModule, declarations: [LinearGaugeComponent, GaugeComponent, GaugeArcComponent, GaugeAxisComponent], imports: [ChartCommonModule, PieChartModule, BarChartModule], exports: [LinearGaugeComponent, GaugeComponent, GaugeArcComponent, GaugeAxisComponent] });
|
|
GaugeModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeModule, imports: [[ChartCommonModule, PieChartModule, BarChartModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: GaugeModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule, PieChartModule, BarChartModule],
|
|
declarations: [LinearGaugeComponent, GaugeComponent, GaugeArcComponent, GaugeAxisComponent],
|
|
exports: [LinearGaugeComponent, GaugeComponent, GaugeArcComponent, GaugeAxisComponent]
|
|
}]
|
|
}] });
|
|
|
|
// The export is needed here to generate a valid polyfills.metadata.json file
|
|
function ngxChartsPolyfills() {
|
|
// IE11 fix
|
|
// Ref: https://github.com/swimlane/ngx-charts/issues/386
|
|
if (typeof SVGElement !== 'undefined' && typeof SVGElement.prototype.contains === 'undefined') {
|
|
SVGElement.prototype.contains = HTMLDivElement.prototype.contains;
|
|
}
|
|
}
|
|
|
|
class SankeyComponent extends BaseChartComponent {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.showLabels = true;
|
|
this.tooltipDisabled = false;
|
|
this.activeEntries = [];
|
|
this.activate = new EventEmitter();
|
|
this.deactivate = new EventEmitter();
|
|
this.margin = [10, 10, 10, 10];
|
|
this.scaleType = ScaleType.Ordinal;
|
|
this.styleTypes = StyleTypes;
|
|
}
|
|
update() {
|
|
super.update();
|
|
this.dims = calculateViewDimensions({
|
|
width: this.width,
|
|
height: this.height,
|
|
margins: this.margin,
|
|
legendType: this.scaleType
|
|
});
|
|
const linkDefs = this.results;
|
|
const nodeDefs = Array.from(new Set(linkDefs.flatMap(l => [l.source, l.target])), (name) => ({
|
|
name,
|
|
value: linkDefs.filter(l => l.source === name).reduce((acc, l) => acc + l.value, 0)
|
|
}));
|
|
// Configure generator
|
|
const sankeyGenerator = sankey()
|
|
.nodeId(d => d.name)
|
|
.nodeAlign(sankeyLeft)
|
|
.nodeWidth(15)
|
|
.nodePadding(10)
|
|
.extent([
|
|
[1, 5],
|
|
[this.dims.width - 1, this.dims.height - 5]
|
|
]);
|
|
// Generate links and nodes
|
|
const data = sankeyGenerator({
|
|
nodes: nodeDefs.map(d => Object.assign({}, d)),
|
|
links: linkDefs.map(d => Object.assign({}, d))
|
|
});
|
|
this.valueDomain = this.getValueDomain(data.nodes);
|
|
this.setColors();
|
|
this.nodeRects = data.nodes.map(node => {
|
|
const rect = {
|
|
x: node.x0,
|
|
y: node.y0,
|
|
height: node.y1 - node.y0,
|
|
width: node.x1 - node.x0,
|
|
fill: this.colors.getColor(node.name),
|
|
tooltip: this.getNodeTooltipText(node),
|
|
rx: 5,
|
|
data: {
|
|
name: node.name,
|
|
value: node.value
|
|
},
|
|
transform: '',
|
|
label: this.labelFormatting ? this.labelFormatting(node.name) : node.name,
|
|
labelAnchor: TextAnchor.Start
|
|
};
|
|
rect.labelAnchor = this.getTextAnchor(node);
|
|
rect.transform = `translate(${rect.x},${rect.y})`;
|
|
return rect;
|
|
});
|
|
this.linkPaths = data.links.map(link => {
|
|
const gradientId = 'mask' + id().toString();
|
|
const linkPath = {
|
|
path: sankeyLinkHorizontal()(link),
|
|
strokeWidth: Math.max(1, link.width),
|
|
tooltip: this.getLinkTooltipText(link.source, link.target, link.value),
|
|
id: gradientId,
|
|
gradientFill: `url(#${gradientId})`,
|
|
source: link.source,
|
|
target: link.target,
|
|
startColor: this.colors.getColor(link.source.name),
|
|
endColor: this.colors.getColor(link.target.name),
|
|
data: {
|
|
source: link.source.name,
|
|
target: link.target.name,
|
|
value: link.value
|
|
}
|
|
};
|
|
return linkPath;
|
|
});
|
|
this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
|
}
|
|
getNodeTooltipText(node) {
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(node.name)}</span>
|
|
<span class="tooltip-val">${node.value.toLocaleString()}</span>
|
|
`;
|
|
}
|
|
getLinkTooltipText(sourceNode, targetNode, value) {
|
|
return `
|
|
<span class="tooltip-label">${escapeLabel(sourceNode.name)} • ${escapeLabel(targetNode.name)}</span>
|
|
<span class="tooltip-val">${value.toLocaleString()} (${(value / sourceNode.value).toLocaleString(undefined, {
|
|
style: 'percent',
|
|
maximumFractionDigits: 2
|
|
})})</span>
|
|
`;
|
|
}
|
|
getTextAnchor(node) {
|
|
if (node.layer === 0) {
|
|
return TextAnchor.Start;
|
|
}
|
|
else {
|
|
return TextAnchor.End;
|
|
}
|
|
}
|
|
onClick(data) {
|
|
this.select.emit(data);
|
|
}
|
|
setColors() {
|
|
this.colors = new ColorHelper(this.scheme, this.scaleType, this.valueDomain);
|
|
}
|
|
getValueDomain(nodes) {
|
|
return nodes.map(n => n.name);
|
|
}
|
|
}
|
|
SankeyComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SankeyComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
SankeyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: SankeyComponent, selector: "ngx-charts-sankey", inputs: { showLabels: "showLabels", gradient: "gradient", tooltipDisabled: "tooltipDisabled", activeEntries: "activeEntries", labelFormatting: "labelFormatting" }, outputs: { activate: "activate", deactivate: "deactivate" }, queries: [{ propertyName: "tooltipTemplate", first: true, predicate: ["tooltipTemplate"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
<ngx-charts-chart [view]="[width, height]" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="sankey chart">
|
|
<svg:g
|
|
*ngFor="let link of linkPaths"
|
|
class="link"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipPlacement]="'top'"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : link.tooltip"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="link.data"
|
|
>
|
|
<svg:defs>
|
|
<svg:linearGradient
|
|
[attr.id]="link.id"
|
|
gradientUnits="userSpaceOnUse"
|
|
[attr.x1]="link.source.x1"
|
|
[attr.x2]="link.target.x0"
|
|
>
|
|
<svg:stop offset="0%" [attr.stop-color]="link.startColor"></svg:stop>
|
|
<svg:stop offset="100%" [attr.stop-color]="link.endColor"></svg:stop>
|
|
</svg:linearGradient>
|
|
</svg:defs>
|
|
<svg:path
|
|
[attr.d]="link.path"
|
|
[attr.stroke]="link.gradientFill"
|
|
[attr.stroke-width]="link.strokeWidth"
|
|
stroke-opacity="0.5"
|
|
fill="none"
|
|
(click)="select.emit(link.data)"
|
|
(mouseenter)="activate.emit(link.data)"
|
|
></svg:path>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let rect of nodeRects" [attr.transform]="rect.transform" class="node">
|
|
<svg:rect
|
|
[attr.x]="0"
|
|
[attr.y]="0"
|
|
[attr.width]="rect.width"
|
|
[attr.height]="rect.height"
|
|
[attr.fill]="rect.fill"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipPlacement]="'top'"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : rect.tooltip"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="rect.data"
|
|
(click)="select.emit(rect.data)"
|
|
(mouseenter)="activate.emit(rect.data)"
|
|
></svg:rect>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let rect of nodeRects" [attr.transform]="rect.transform">
|
|
<svg:text
|
|
*ngIf="showLabels && rect.height > 15"
|
|
class="label"
|
|
[attr.x]="rect.width + 5"
|
|
[attr.y]="rect.height / 2"
|
|
[attr.text-anchor]="rect.labelAnchor"
|
|
dy="0.35em"
|
|
[attr.dx]="rect.labelAnchor === 'end' ? -25 : 0"
|
|
>
|
|
{{ rect.label }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, isInline: true, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"], components: [{ type: ChartComponent, selector: "ngx-charts-chart", inputs: ["view", "showLegend", "legendOptions", "legendType", "activeEntries", "animations"], outputs: ["legendLabelClick", "legendLabelActivate", "legendLabelDeactivate"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SankeyComponent, decorators: [{
|
|
type: Component,
|
|
args: [{ selector: 'ngx-charts-sankey', template: `
|
|
<ngx-charts-chart [view]="[width, height]" [animations]="animations">
|
|
<svg:g [attr.transform]="transform" class="sankey chart">
|
|
<svg:g
|
|
*ngFor="let link of linkPaths"
|
|
class="link"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipPlacement]="'top'"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : link.tooltip"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="link.data"
|
|
>
|
|
<svg:defs>
|
|
<svg:linearGradient
|
|
[attr.id]="link.id"
|
|
gradientUnits="userSpaceOnUse"
|
|
[attr.x1]="link.source.x1"
|
|
[attr.x2]="link.target.x0"
|
|
>
|
|
<svg:stop offset="0%" [attr.stop-color]="link.startColor"></svg:stop>
|
|
<svg:stop offset="100%" [attr.stop-color]="link.endColor"></svg:stop>
|
|
</svg:linearGradient>
|
|
</svg:defs>
|
|
<svg:path
|
|
[attr.d]="link.path"
|
|
[attr.stroke]="link.gradientFill"
|
|
[attr.stroke-width]="link.strokeWidth"
|
|
stroke-opacity="0.5"
|
|
fill="none"
|
|
(click)="select.emit(link.data)"
|
|
(mouseenter)="activate.emit(link.data)"
|
|
></svg:path>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let rect of nodeRects" [attr.transform]="rect.transform" class="node">
|
|
<svg:rect
|
|
[attr.x]="0"
|
|
[attr.y]="0"
|
|
[attr.width]="rect.width"
|
|
[attr.height]="rect.height"
|
|
[attr.fill]="rect.fill"
|
|
ngx-tooltip
|
|
[tooltipDisabled]="tooltipDisabled"
|
|
[tooltipType]="styleTypes.tooltip"
|
|
[tooltipPlacement]="'top'"
|
|
[tooltipTitle]="tooltipTemplate ? undefined : rect.tooltip"
|
|
[tooltipTemplate]="tooltipTemplate"
|
|
[tooltipContext]="rect.data"
|
|
(click)="select.emit(rect.data)"
|
|
(mouseenter)="activate.emit(rect.data)"
|
|
></svg:rect>
|
|
</svg:g>
|
|
|
|
<svg:g *ngFor="let rect of nodeRects" [attr.transform]="rect.transform">
|
|
<svg:text
|
|
*ngIf="showLabels && rect.height > 15"
|
|
class="label"
|
|
[attr.x]="rect.width + 5"
|
|
[attr.y]="rect.height / 2"
|
|
[attr.text-anchor]="rect.labelAnchor"
|
|
dy="0.35em"
|
|
[attr.dx]="rect.labelAnchor === 'end' ? -25 : 0"
|
|
>
|
|
{{ rect.label }}
|
|
</svg:text>
|
|
</svg:g>
|
|
</svg:g>
|
|
</ngx-charts-chart>
|
|
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: [".ngx-charts-outer{animation:chartFadeIn linear .6s}@keyframes chartFadeIn{0%{opacity:0}20%{opacity:0}to{opacity:1}}.ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.ngx-charts .node,.ngx-charts .link,.ngx-charts .arc{cursor:pointer}.ngx-charts .bar.active,.ngx-charts .bar:hover,.ngx-charts .cell.active,.ngx-charts .cell:hover,.ngx-charts .arc.active,.ngx-charts .arc:hover,.ngx-charts .node.active,.ngx-charts .node:hover,.ngx-charts .link.active,.ngx-charts .link:hover,.ngx-charts .card.active,.ngx-charts .card:hover{opacity:.8;transition:opacity .1s ease-in-out}.ngx-charts .bar:focus,.ngx-charts .cell:focus,.ngx-charts .arc:focus,.ngx-charts .node:focus,.ngx-charts .link:focus,.ngx-charts .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.hidden,.ngx-charts .node.hidden,.ngx-charts .link.hidden,.ngx-charts .card.hidden{display:none}.ngx-charts g:focus{outline:none}.ngx-charts .line-series.inactive,.ngx-charts .line-series-range.inactive,.ngx-charts .polar-series-path.inactive,.ngx-charts .polar-series-area.inactive,.ngx-charts .area-series.inactive{transition:opacity .1s ease-in-out;opacity:.2}.ngx-charts .line-highlight{display:none}.ngx-charts .line-highlight.active{display:block}.ngx-charts .area{opacity:.6}.ngx-charts .circle:hover{cursor:pointer}.ngx-charts .label{font-size:12px;font-weight:400}.ngx-charts .tooltip-anchor{fill:#000}.ngx-charts .gridline-path{stroke:#ddd;stroke-width:1;fill:none}.ngx-charts .refline-path{stroke:#a8b2c7;stroke-width:1;stroke-dasharray:5;stroke-dashoffset:5}.ngx-charts .refline-label{font-size:9px}.ngx-charts .reference-area{fill-opacity:.05;fill:#000}.ngx-charts .gridline-path-dotted{stroke:#ddd;stroke-width:1;fill:none;stroke-dasharray:1,20;stroke-dashoffset:3}.ngx-charts .grid-panel rect{fill:none}.ngx-charts .grid-panel.odd rect{fill:#0000000d}\n"] }]
|
|
}], propDecorators: { showLabels: [{
|
|
type: Input
|
|
}], gradient: [{
|
|
type: Input
|
|
}], tooltipDisabled: [{
|
|
type: Input
|
|
}], activeEntries: [{
|
|
type: Input
|
|
}], labelFormatting: [{
|
|
type: Input
|
|
}], activate: [{
|
|
type: Output
|
|
}], deactivate: [{
|
|
type: Output
|
|
}], tooltipTemplate: [{
|
|
type: ContentChild,
|
|
args: ['tooltipTemplate']
|
|
}] } });
|
|
|
|
class SankeyModule {
|
|
}
|
|
SankeyModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SankeyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
SankeyModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SankeyModule, declarations: [SankeyComponent], imports: [ChartCommonModule], exports: [SankeyComponent] });
|
|
SankeyModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SankeyModule, imports: [[ChartCommonModule]] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: SankeyModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [ChartCommonModule],
|
|
declarations: [SankeyComponent],
|
|
exports: [SankeyComponent]
|
|
}]
|
|
}] });
|
|
|
|
class NgxChartsModule {
|
|
constructor() {
|
|
ngxChartsPolyfills();
|
|
}
|
|
}
|
|
NgxChartsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NgxChartsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
NgxChartsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NgxChartsModule, exports: [ChartCommonModule,
|
|
AreaChartModule,
|
|
BarChartModule,
|
|
BoxChartModule,
|
|
BubbleChartModule,
|
|
HeatMapModule,
|
|
SankeyModule,
|
|
LineChartModule,
|
|
PolarChartModule,
|
|
NumberCardModule,
|
|
PieChartModule,
|
|
TreeMapModule,
|
|
GaugeModule] });
|
|
NgxChartsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NgxChartsModule, imports: [ChartCommonModule,
|
|
AreaChartModule,
|
|
BarChartModule,
|
|
BoxChartModule,
|
|
BubbleChartModule,
|
|
HeatMapModule,
|
|
SankeyModule,
|
|
LineChartModule,
|
|
PolarChartModule,
|
|
NumberCardModule,
|
|
PieChartModule,
|
|
TreeMapModule,
|
|
GaugeModule] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: NgxChartsModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
exports: [
|
|
ChartCommonModule,
|
|
AreaChartModule,
|
|
BarChartModule,
|
|
BoxChartModule,
|
|
BubbleChartModule,
|
|
HeatMapModule,
|
|
SankeyModule,
|
|
LineChartModule,
|
|
PolarChartModule,
|
|
NumberCardModule,
|
|
PieChartModule,
|
|
TreeMapModule,
|
|
GaugeModule
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return []; } });
|
|
|
|
function tickFormat(fieldType, groupByType) {
|
|
return function (label) {
|
|
if (label === 'No Value' || label === 'Other') {
|
|
return label;
|
|
}
|
|
if (fieldType === 'date' && groupByType === 'groupBy') {
|
|
const formatter = timeFormat('MM/DD/YYYY');
|
|
return formatter(label);
|
|
}
|
|
return label.toString();
|
|
};
|
|
}
|
|
|
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
|
|
/*
|
|
* Public API Surface of ngx-charts
|
|
*/
|
|
|
|
/**
|
|
* Generated bundle index. Do not edit.
|
|
*/
|
|
|
|
export { AdvancedLegendComponent, AdvancedPieChartComponent, AreaChartComponent, AreaChartModule, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaComponent, AreaSeriesComponent, AxesModule, AxisLabelComponent, BarChartModule, BarChartType, BarComponent, BarHorizontal2DComponent, BarHorizontalComponent, BarHorizontalNormalizedComponent, BarHorizontalStackedComponent, BarLabelComponent, BarOrientation, BarVertical2DComponent, BarVerticalComponent, BarVerticalNormalizedComponent, BarVerticalStackedComponent, BaseChartComponent, BoxChartComponent, BoxChartModule, BoxComponent, BoxSeriesComponent, BubbleChartComponent, BubbleChartModule, BubbleSeriesComponent, CardComponent, CardSeriesComponent, ChartCommonModule, ChartComponent, CircleComponent, CircleSeriesComponent, ColorHelper, CountUpDirective, D0Types, GaugeArcComponent, GaugeAxisComponent, GaugeComponent, GaugeModule, GridPanelComponent, GridPanelSeriesComponent, HeatCellSeriesComponent, HeatMapCellComponent, HeatMapComponent, HeatMapModule, LegendComponent, LegendEntryComponent, LegendPosition, LegendType, LineChartComponent, LineChartModule, LineComponent, LineSeriesComponent, LinearGaugeComponent, NgxChartsModule, NumberCardComponent, NumberCardModule, Orientation, PieArcComponent, PieChartComponent, PieChartModule, PieGridComponent, PieGridSeriesComponent, PieLabelComponent, PieSeriesComponent, PlacementTypes, PolarChartComponent, PolarChartModule, PolarSeriesComponent, SankeyComponent, SankeyModule, ScaleLegendComponent, ScaleType, SeriesHorizontal, SeriesType, SeriesVerticalComponent, ShowTypes, StyleTypes, SvgLinearGradientComponent, SvgRadialGradientComponent, TextAnchor, Timeline, TooltipArea, TooltipContentComponent, TooltipDirective, TooltipModule, TooltipService, TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent, TreeMapModule, VisibilityObserver, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent, calculateViewDimensions, colorSets, count, decimalChecker, escapeLabel, formatLabel, getDomain, getScale, getScaleType, getTickLines, getUniqueXDomainValues, getXDomainArray, gridLayout, gridSize, hexToRgb, id, invertColor, reduceTicks, shadeRGBColor, sortByDomain, sortByTime, sortLinear, throttle, throttleable, tickFormat, trimLabel };
|
|
//# sourceMappingURL=swimlane-ngx-charts.mjs.map
|