1 | import { Injectable, ApplicationRef, ComponentFactoryResolver, Injector, Component, ViewEncapsulation, ElementRef, Renderer2, Inject, PLATFORM_ID, Input, ViewChild, HostBinding, HostListener, EventEmitter, ChangeDetectionStrategy, Output, Directive, NgZone, ChangeDetectorRef, NgModule, ViewContainerRef, ContentChild } from '@angular/core';
|
2 | import { isPlatformBrowser, isPlatformServer, CommonModule } from '@angular/common';
|
3 | import { trigger, transition, style, animate } from '@angular/animations';
|
4 | import { DomPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
|
5 | import { __decorate } from 'tslib';
|
6 | import { fromEvent } from 'rxjs';
|
7 | import { debounceTime } from 'rxjs/operators';
|
8 | import { select } from 'd3-selection';
|
9 | import { brushX } from 'd3-brush';
|
10 | import { scaleTime, scaleLinear, scalePoint, scaleOrdinal, scaleQuantile, scaleBand } from 'd3-scale';
|
11 | import { curveLinear, area, line, curveCardinalClosed, lineRadial, arc, pie } from 'd3-shape';
|
12 | import { range, min, max, quantile } from 'd3-array';
|
13 | import { interpolate } from 'd3-interpolate';
|
14 | import { easeSinInOut } from 'd3-ease';
|
15 | import cloneDeep from 'clone-deep';
|
16 | import { format } from 'd3-format';
|
17 | import * as d3_color from 'd3-color';
|
18 | import { treemap, stratify } from 'd3-hierarchy';
|
19 | import { timeFormat } from 'd3-time-format';
|
20 |
|
21 | function isViewContainerRef(x) {
|
22 | return x.element;
|
23 | }
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | class InjectionService {
|
32 | constructor(applicationRef, componentFactoryResolver, injector) {
|
33 | this.applicationRef = applicationRef;
|
34 | this.componentFactoryResolver = componentFactoryResolver;
|
35 | this.injector = injector;
|
36 | }
|
37 | |
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | static setGlobalRootViewContainer(container) {
|
44 | InjectionService.globalRootViewContainer = container;
|
45 | }
|
46 | |
47 |
|
48 |
|
49 |
|
50 |
|
51 | getRootViewContainer() {
|
52 | if (this._container)
|
53 | return this._container;
|
54 | if (InjectionService.globalRootViewContainer)
|
55 | return InjectionService.globalRootViewContainer;
|
56 | if (this.applicationRef.components.length)
|
57 | return this.applicationRef.components[0];
|
58 | throw new Error('View Container not found! ngUpgrade needs to manually set this via setRootViewContainer or setGlobalRootViewContainer.');
|
59 | }
|
60 | |
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | setRootViewContainer(container) {
|
69 | this._container = container;
|
70 | }
|
71 | |
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | getComponentRootNode(component) {
|
79 | if (isViewContainerRef(component)) {
|
80 | return component.element.nativeElement;
|
81 | }
|
82 | if (component.hostView && component.hostView.rootNodes.length > 0) {
|
83 | return component.hostView.rootNodes[0];
|
84 | }
|
85 |
|
86 | return component.location.nativeElement;
|
87 | }
|
88 | |
89 |
|
90 |
|
91 |
|
92 |
|
93 | getRootViewContainerNode(component) {
|
94 | return this.getComponentRootNode(component);
|
95 | }
|
96 | |
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 | projectComponentBindings(component, bindings) {
|
105 | if (bindings) {
|
106 | if (bindings.inputs !== undefined) {
|
107 | const bindingKeys = Object.getOwnPropertyNames(bindings.inputs);
|
108 | for (const bindingName of bindingKeys) {
|
109 | component.instance[bindingName] = bindings.inputs[bindingName];
|
110 | }
|
111 | }
|
112 | if (bindings.outputs !== undefined) {
|
113 | const eventKeys = Object.getOwnPropertyNames(bindings.outputs);
|
114 | for (const eventName of eventKeys) {
|
115 | component.instance[eventName] = bindings.outputs[eventName];
|
116 | }
|
117 | }
|
118 | }
|
119 | return component;
|
120 | }
|
121 | |
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | appendComponent(componentClass, bindings = {}, location) {
|
131 | if (!location)
|
132 | location = this.getRootViewContainer();
|
133 | const appendLocation = this.getComponentRootNode(location);
|
134 | const portalHost = new DomPortalOutlet(appendLocation, this.componentFactoryResolver, this.applicationRef, this.injector);
|
135 | const portal = new ComponentPortal(componentClass);
|
136 | const componentRef = portalHost.attach(portal);
|
137 | this.projectComponentBindings(componentRef, bindings);
|
138 | return componentRef;
|
139 | }
|
140 | }
|
141 | InjectionService.globalRootViewContainer = null;
|
142 | InjectionService.decorators = [
|
143 | { type: Injectable }
|
144 | ];
|
145 | InjectionService.ctorParameters = () => [
|
146 | { type: ApplicationRef },
|
147 | { type: ComponentFactoryResolver },
|
148 | { type: Injector }
|
149 | ];
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | function throttle(func, wait, options) {
|
156 | options = options || {};
|
157 | let context;
|
158 | let args;
|
159 | let result;
|
160 | let timeout = null;
|
161 | let previous = 0;
|
162 | function later() {
|
163 | previous = options.leading === false ? 0 : +new Date();
|
164 | timeout = null;
|
165 | result = func.apply(context, args);
|
166 | }
|
167 | return function () {
|
168 | const now = +new Date();
|
169 | if (!previous && options.leading === false) {
|
170 | previous = now;
|
171 | }
|
172 | const remaining = wait - (now - previous);
|
173 | context = this;
|
174 | args = arguments;
|
175 | if (remaining <= 0) {
|
176 | clearTimeout(timeout);
|
177 | timeout = null;
|
178 | previous = now;
|
179 | result = func.apply(context, args);
|
180 | }
|
181 | else if (!timeout && options.trailing !== false) {
|
182 | timeout = setTimeout(later, remaining);
|
183 | }
|
184 | return result;
|
185 | };
|
186 | }
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 | function throttleable(duration, options) {
|
196 | return function innerDecorator(target, key, descriptor) {
|
197 | return {
|
198 | configurable: true,
|
199 | enumerable: descriptor.enumerable,
|
200 | get: function getter() {
|
201 | Object.defineProperty(this, key, {
|
202 | configurable: true,
|
203 | enumerable: descriptor.enumerable,
|
204 | value: throttle(descriptor.value, duration, options)
|
205 | });
|
206 | return this[key];
|
207 | }
|
208 | };
|
209 | };
|
210 | }
|
211 |
|
212 | var PlacementTypes;
|
213 | (function (PlacementTypes) {
|
214 | PlacementTypes["Top"] = "top";
|
215 | PlacementTypes["Bottom"] = "bottom";
|
216 | PlacementTypes["Left"] = "left";
|
217 | PlacementTypes["Right"] = "right";
|
218 | PlacementTypes["Center"] = "center";
|
219 | })(PlacementTypes || (PlacementTypes = {}));
|
220 |
|
221 | const caretOffset = 7;
|
222 | function verticalPosition(elDimensions, popoverDimensions, alignment) {
|
223 | if (alignment === PlacementTypes.Top) {
|
224 | return elDimensions.top - caretOffset;
|
225 | }
|
226 | if (alignment === PlacementTypes.Bottom) {
|
227 | return elDimensions.top + elDimensions.height - popoverDimensions.height + caretOffset;
|
228 | }
|
229 | if (alignment === PlacementTypes.Center) {
|
230 | return elDimensions.top + elDimensions.height / 2 - popoverDimensions.height / 2;
|
231 | }
|
232 | return undefined;
|
233 | }
|
234 | function horizontalPosition(elDimensions, popoverDimensions, alignment) {
|
235 | if (alignment === PlacementTypes.Left) {
|
236 | return elDimensions.left - caretOffset;
|
237 | }
|
238 | if (alignment === PlacementTypes.Right) {
|
239 | return elDimensions.left + elDimensions.width - popoverDimensions.width + caretOffset;
|
240 | }
|
241 | if (alignment === PlacementTypes.Center) {
|
242 | return elDimensions.left + elDimensions.width / 2 - popoverDimensions.width / 2;
|
243 | }
|
244 | return undefined;
|
245 | }
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 | class PositionHelper {
|
252 | |
253 |
|
254 |
|
255 |
|
256 |
|
257 | static calculateVerticalAlignment(elDimensions, popoverDimensions, alignment) {
|
258 | let result = verticalPosition(elDimensions, popoverDimensions, alignment);
|
259 | if (result + popoverDimensions.height > window.innerHeight) {
|
260 | result = window.innerHeight - popoverDimensions.height;
|
261 | }
|
262 | return result;
|
263 | }
|
264 | |
265 |
|
266 |
|
267 |
|
268 |
|
269 | static calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
|
270 | let result;
|
271 | if (alignment === PlacementTypes.Top) {
|
272 | result = elDimensions.height / 2 - caretDimensions.height / 2 + caretOffset;
|
273 | }
|
274 | if (alignment === PlacementTypes.Bottom) {
|
275 | result = popoverDimensions.height - elDimensions.height / 2 - caretDimensions.height / 2 - caretOffset;
|
276 | }
|
277 | if (alignment === PlacementTypes.Center) {
|
278 | result = popoverDimensions.height / 2 - caretDimensions.height / 2;
|
279 | }
|
280 | const popoverPosition = verticalPosition(elDimensions, popoverDimensions, alignment);
|
281 | if (popoverPosition + popoverDimensions.height > window.innerHeight) {
|
282 | result += popoverPosition + popoverDimensions.height - window.innerHeight;
|
283 | }
|
284 | return result;
|
285 | }
|
286 | |
287 |
|
288 |
|
289 |
|
290 |
|
291 | static calculateHorizontalAlignment(elDimensions, popoverDimensions, alignment) {
|
292 | let result = horizontalPosition(elDimensions, popoverDimensions, alignment);
|
293 | if (result + popoverDimensions.width > window.innerWidth) {
|
294 | result = window.innerWidth - popoverDimensions.width;
|
295 | }
|
296 | return result;
|
297 | }
|
298 | |
299 |
|
300 |
|
301 |
|
302 |
|
303 | static calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
|
304 | let result;
|
305 | if (alignment === PlacementTypes.Left) {
|
306 | result = elDimensions.width / 2 - caretDimensions.width / 2 + caretOffset;
|
307 | }
|
308 | if (alignment === PlacementTypes.Right) {
|
309 | result = popoverDimensions.width - elDimensions.width / 2 - caretDimensions.width / 2 - caretOffset;
|
310 | }
|
311 | if (alignment === PlacementTypes.Center) {
|
312 | result = popoverDimensions.width / 2 - caretDimensions.width / 2;
|
313 | }
|
314 | const popoverPosition = horizontalPosition(elDimensions, popoverDimensions, alignment);
|
315 | if (popoverPosition + popoverDimensions.width > window.innerWidth) {
|
316 | result += popoverPosition + popoverDimensions.width - window.innerWidth;
|
317 | }
|
318 | return result;
|
319 | }
|
320 | |
321 |
|
322 |
|
323 |
|
324 |
|
325 | static shouldFlip(elDimensions, popoverDimensions, placement, spacing) {
|
326 | let flip = false;
|
327 | if (placement === PlacementTypes.Right) {
|
328 | if (elDimensions.left + elDimensions.width + popoverDimensions.width + spacing > window.innerWidth) {
|
329 | flip = true;
|
330 | }
|
331 | }
|
332 | if (placement === PlacementTypes.Left) {
|
333 | if (elDimensions.left - popoverDimensions.width - spacing < 0) {
|
334 | flip = true;
|
335 | }
|
336 | }
|
337 | if (placement === PlacementTypes.Top) {
|
338 | if (elDimensions.top - popoverDimensions.height - spacing < 0) {
|
339 | flip = true;
|
340 | }
|
341 | }
|
342 | if (placement === PlacementTypes.Bottom) {
|
343 | if (elDimensions.top + elDimensions.height + popoverDimensions.height + spacing > window.innerHeight) {
|
344 | flip = true;
|
345 | }
|
346 | }
|
347 | return flip;
|
348 | }
|
349 | |
350 |
|
351 |
|
352 |
|
353 |
|
354 | static positionCaret(placement, elmDim, hostDim, caretDimensions, alignment) {
|
355 | let top = 0;
|
356 | let left = 0;
|
357 | if (placement === PlacementTypes.Right) {
|
358 | left = -7;
|
359 | top = PositionHelper.calculateVerticalCaret(hostDim, elmDim, caretDimensions, alignment);
|
360 | }
|
361 | else if (placement === PlacementTypes.Left) {
|
362 | left = elmDim.width;
|
363 | top = PositionHelper.calculateVerticalCaret(hostDim, elmDim, caretDimensions, alignment);
|
364 | }
|
365 | else if (placement === PlacementTypes.Top) {
|
366 | top = elmDim.height;
|
367 | left = PositionHelper.calculateHorizontalCaret(hostDim, elmDim, caretDimensions, alignment);
|
368 | }
|
369 | else if (placement === PlacementTypes.Bottom) {
|
370 | top = -7;
|
371 | left = PositionHelper.calculateHorizontalCaret(hostDim, elmDim, caretDimensions, alignment);
|
372 | }
|
373 | return { top, left };
|
374 | }
|
375 | |
376 |
|
377 |
|
378 |
|
379 |
|
380 | static positionContent(placement, elmDim, hostDim, spacing, alignment) {
|
381 | let top = 0;
|
382 | let left = 0;
|
383 | if (placement === PlacementTypes.Right) {
|
384 | left = hostDim.left + hostDim.width + spacing;
|
385 | top = PositionHelper.calculateVerticalAlignment(hostDim, elmDim, alignment);
|
386 | }
|
387 | else if (placement === PlacementTypes.Left) {
|
388 | left = hostDim.left - elmDim.width - spacing;
|
389 | top = PositionHelper.calculateVerticalAlignment(hostDim, elmDim, alignment);
|
390 | }
|
391 | else if (placement === PlacementTypes.Top) {
|
392 | top = hostDim.top - elmDim.height - spacing;
|
393 | left = PositionHelper.calculateHorizontalAlignment(hostDim, elmDim, alignment);
|
394 | }
|
395 | else if (placement === PlacementTypes.Bottom) {
|
396 | top = hostDim.top + hostDim.height + spacing;
|
397 | left = PositionHelper.calculateHorizontalAlignment(hostDim, elmDim, alignment);
|
398 | }
|
399 | return { top, left };
|
400 | }
|
401 | |
402 |
|
403 |
|
404 |
|
405 |
|
406 | static determinePlacement(placement, elmDim, hostDim, spacing) {
|
407 | const shouldFlip = PositionHelper.shouldFlip(hostDim, elmDim, placement, spacing);
|
408 | if (shouldFlip) {
|
409 | if (placement === PlacementTypes.Right) {
|
410 | return PlacementTypes.Left;
|
411 | }
|
412 | else if (placement === PlacementTypes.Left) {
|
413 | return PlacementTypes.Right;
|
414 | }
|
415 | else if (placement === PlacementTypes.Top) {
|
416 | return PlacementTypes.Bottom;
|
417 | }
|
418 | else if (placement === PlacementTypes.Bottom) {
|
419 | return PlacementTypes.Top;
|
420 | }
|
421 | }
|
422 | return placement;
|
423 | }
|
424 | }
|
425 |
|
426 | class TooltipContentComponent {
|
427 | constructor(element, renderer, platformId) {
|
428 | this.element = element;
|
429 | this.renderer = renderer;
|
430 | this.platformId = platformId;
|
431 | }
|
432 | get cssClasses() {
|
433 | let clz = 'ngx-charts-tooltip-content';
|
434 | clz += ` position-${this.placement}`;
|
435 | clz += ` type-${this.type}`;
|
436 | clz += ` ${this.cssClass}`;
|
437 | return clz;
|
438 | }
|
439 | ngAfterViewInit() {
|
440 | setTimeout(this.position.bind(this));
|
441 | }
|
442 | position() {
|
443 | if (!isPlatformBrowser(this.platformId)) {
|
444 | return;
|
445 | }
|
446 | const nativeElm = this.element.nativeElement;
|
447 | const hostDim = this.host.nativeElement.getBoundingClientRect();
|
448 |
|
449 | if (!hostDim.height && !hostDim.width)
|
450 | return;
|
451 | const elmDim = nativeElm.getBoundingClientRect();
|
452 | this.checkFlip(hostDim, elmDim);
|
453 | this.positionContent(nativeElm, hostDim, elmDim);
|
454 | if (this.showCaret) {
|
455 | this.positionCaret(hostDim, elmDim);
|
456 | }
|
457 |
|
458 | setTimeout(() => this.renderer.addClass(nativeElm, 'animate'), 1);
|
459 | }
|
460 | positionContent(nativeElm, hostDim, elmDim) {
|
461 | const { top, left } = PositionHelper.positionContent(this.placement, elmDim, hostDim, this.spacing, this.alignment);
|
462 | this.renderer.setStyle(nativeElm, 'top', `${top}px`);
|
463 | this.renderer.setStyle(nativeElm, 'left', `${left}px`);
|
464 | }
|
465 | positionCaret(hostDim, elmDim) {
|
466 | const caretElm = this.caretElm.nativeElement;
|
467 | const caretDimensions = caretElm.getBoundingClientRect();
|
468 | const { top, left } = PositionHelper.positionCaret(this.placement, elmDim, hostDim, caretDimensions, this.alignment);
|
469 | this.renderer.setStyle(caretElm, 'top', `${top}px`);
|
470 | this.renderer.setStyle(caretElm, 'left', `${left}px`);
|
471 | }
|
472 | checkFlip(hostDim, elmDim) {
|
473 | this.placement = PositionHelper.determinePlacement(this.placement, elmDim, hostDim, this.spacing);
|
474 | }
|
475 | onWindowResize() {
|
476 | this.position();
|
477 | }
|
478 | }
|
479 | TooltipContentComponent.decorators = [
|
480 | { type: Component, args: [{
|
481 | selector: 'ngx-tooltip-content',
|
482 | template: `
|
483 | <div>
|
484 | <span #caretElm [hidden]="!showCaret" class="tooltip-caret position-{{ this.placement }}"> </span>
|
485 | <div class="tooltip-content">
|
486 | <span *ngIf="!title">
|
487 | <ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ model: context }"> </ng-template>
|
488 | </span>
|
489 | <span *ngIf="title" [innerHTML]="title"> </span>
|
490 | </div>
|
491 | </div>
|
492 | `,
|
493 | encapsulation: ViewEncapsulation.None,
|
494 | styles: [".ngx-charts-tooltip-content{position:fixed;border-radius:3px;z-index:5000;display:block;font-weight:normal;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"]
|
495 | },] }
|
496 | ];
|
497 | TooltipContentComponent.ctorParameters = () => [
|
498 | { type: ElementRef },
|
499 | { type: Renderer2 },
|
500 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
501 | ];
|
502 | TooltipContentComponent.propDecorators = {
|
503 | host: [{ type: Input }],
|
504 | showCaret: [{ type: Input }],
|
505 | type: [{ type: Input }],
|
506 | placement: [{ type: Input }],
|
507 | alignment: [{ type: Input }],
|
508 | spacing: [{ type: Input }],
|
509 | cssClass: [{ type: Input }],
|
510 | title: [{ type: Input }],
|
511 | template: [{ type: Input }],
|
512 | context: [{ type: Input }],
|
513 | caretElm: [{ type: ViewChild, args: ['caretElm',] }],
|
514 | cssClasses: [{ type: HostBinding, args: ['class',] }],
|
515 | onWindowResize: [{ type: HostListener, args: ['window:resize',] }]
|
516 | };
|
517 | __decorate([
|
518 | throttleable(100)
|
519 | ], TooltipContentComponent.prototype, "onWindowResize", null);
|
520 |
|
521 | class InjectionRegisteryService {
|
522 | constructor(injectionService) {
|
523 | this.injectionService = injectionService;
|
524 | this.defaults = {};
|
525 | this.components = new Map();
|
526 | }
|
527 | getByType(type = this.type) {
|
528 | return this.components.get(type);
|
529 | }
|
530 | create(bindings) {
|
531 | return this.createByType(this.type, bindings);
|
532 | }
|
533 | createByType(type, bindings) {
|
534 | bindings = this.assignDefaults(bindings);
|
535 | const component = this.injectComponent(type, bindings);
|
536 | this.register(type, component);
|
537 | return component;
|
538 | }
|
539 | destroy(instance) {
|
540 | const compsByType = this.components.get(instance.componentType);
|
541 | if (compsByType && compsByType.length) {
|
542 | const idx = compsByType.indexOf(instance);
|
543 | if (idx > -1) {
|
544 | const component = compsByType[idx];
|
545 | component.destroy();
|
546 | compsByType.splice(idx, 1);
|
547 | }
|
548 | }
|
549 | }
|
550 | destroyAll() {
|
551 | this.destroyByType(this.type);
|
552 | }
|
553 | destroyByType(type) {
|
554 | const comps = this.components.get(type);
|
555 | if (comps && comps.length) {
|
556 | let i = comps.length - 1;
|
557 | while (i >= 0) {
|
558 | this.destroy(comps[i--]);
|
559 | }
|
560 | }
|
561 | }
|
562 | injectComponent(type, bindings) {
|
563 | return this.injectionService.appendComponent(type, bindings);
|
564 | }
|
565 | assignDefaults(bindings) {
|
566 | const inputs = Object.assign({}, this.defaults.inputs);
|
567 | const outputs = Object.assign({}, this.defaults.outputs);
|
568 | if (!bindings.inputs && !bindings.outputs) {
|
569 | bindings = { inputs: bindings };
|
570 | }
|
571 | if (inputs) {
|
572 | bindings.inputs = Object.assign(Object.assign({}, inputs), bindings.inputs);
|
573 | }
|
574 | if (outputs) {
|
575 | bindings.outputs = Object.assign(Object.assign({}, outputs), bindings.outputs);
|
576 | }
|
577 | return bindings;
|
578 | }
|
579 | register(type, component) {
|
580 | if (!this.components.has(type)) {
|
581 | this.components.set(type, []);
|
582 | }
|
583 | const types = this.components.get(type);
|
584 | types.push(component);
|
585 | }
|
586 | }
|
587 |
|
588 | class TooltipService extends InjectionRegisteryService {
|
589 | constructor(injectionService) {
|
590 | super(injectionService);
|
591 | this.type = TooltipContentComponent;
|
592 | }
|
593 | }
|
594 | TooltipService.decorators = [
|
595 | { type: Injectable }
|
596 | ];
|
597 | TooltipService.ctorParameters = () => [
|
598 | { type: InjectionService }
|
599 | ];
|
600 |
|
601 | var LegendPosition;
|
602 | (function (LegendPosition) {
|
603 | LegendPosition["Right"] = "right";
|
604 | LegendPosition["Below"] = "below";
|
605 | })(LegendPosition || (LegendPosition = {}));
|
606 | var LegendType;
|
607 | (function (LegendType) {
|
608 | LegendType["ScaleLegend"] = "scaleLegend";
|
609 | LegendType["Legend"] = "legend";
|
610 | })(LegendType || (LegendType = {}));
|
611 |
|
612 | var ScaleType;
|
613 | (function (ScaleType) {
|
614 | ScaleType["Time"] = "time";
|
615 | ScaleType["Linear"] = "linear";
|
616 | ScaleType["Ordinal"] = "ordinal";
|
617 | ScaleType["Quantile"] = "quantile";
|
618 | })(ScaleType || (ScaleType = {}));
|
619 |
|
620 | class ChartComponent {
|
621 | constructor() {
|
622 | this.showLegend = false;
|
623 | this.animations = true;
|
624 | this.legendLabelClick = new EventEmitter();
|
625 | this.legendLabelActivate = new EventEmitter();
|
626 | this.legendLabelDeactivate = new EventEmitter();
|
627 | this.LegendPosition = LegendPosition;
|
628 | this.LegendType = LegendType;
|
629 | }
|
630 | ngOnChanges(changes) {
|
631 | this.update();
|
632 | }
|
633 | update() {
|
634 | let legendColumns = 0;
|
635 | if (this.showLegend) {
|
636 | this.legendType = this.getLegendType();
|
637 | if (!this.legendOptions || this.legendOptions.position === LegendPosition.Right) {
|
638 | if (this.legendType === LegendType.ScaleLegend) {
|
639 | legendColumns = 1;
|
640 | }
|
641 | else {
|
642 | legendColumns = 2;
|
643 | }
|
644 | }
|
645 | }
|
646 | const chartColumns = 12 - legendColumns;
|
647 | this.chartWidth = Math.floor((this.view[0] * chartColumns) / 12.0);
|
648 | this.legendWidth =
|
649 | !this.legendOptions || this.legendOptions.position === LegendPosition.Right
|
650 | ? Math.floor((this.view[0] * legendColumns) / 12.0)
|
651 | : this.chartWidth;
|
652 | }
|
653 | getLegendType() {
|
654 | return this.legendOptions.scaleType === ScaleType.Linear ? LegendType.ScaleLegend : LegendType.Legend;
|
655 | }
|
656 | }
|
657 | ChartComponent.decorators = [
|
658 | { type: Component, args: [{
|
659 | providers: [TooltipService],
|
660 | selector: 'ngx-charts-chart',
|
661 | template: `
|
662 | <div class="ngx-charts-outer" [style.width.px]="view[0]" [@animationState]="'active'" [@.disabled]="!animations">
|
663 | <svg class="ngx-charts" [attr.width]="chartWidth" [attr.height]="view[1]">
|
664 | <ng-content></ng-content>
|
665 | </svg>
|
666 | <ngx-charts-scale-legend
|
667 | *ngIf="showLegend && legendType === LegendType.ScaleLegend"
|
668 | class="chart-legend"
|
669 | [horizontal]="legendOptions && legendOptions.position === LegendPosition.Below"
|
670 | [valueRange]="legendOptions.domain"
|
671 | [colors]="legendOptions.colors"
|
672 | [height]="view[1]"
|
673 | [width]="legendWidth"
|
674 | >
|
675 | </ngx-charts-scale-legend>
|
676 | <ngx-charts-legend
|
677 | *ngIf="showLegend && legendType === LegendType.Legend"
|
678 | class="chart-legend"
|
679 | [horizontal]="legendOptions && legendOptions.position === LegendPosition.Below"
|
680 | [data]="legendOptions.domain"
|
681 | [title]="legendOptions.title"
|
682 | [colors]="legendOptions.colors"
|
683 | [height]="view[1]"
|
684 | [width]="legendWidth"
|
685 | [activeEntries]="activeEntries"
|
686 | (labelClick)="legendLabelClick.emit($event)"
|
687 | (labelActivate)="legendLabelActivate.emit($event)"
|
688 | (labelDeactivate)="legendLabelDeactivate.emit($event)"
|
689 | >
|
690 | </ngx-charts-legend>
|
691 | </div>
|
692 | `,
|
693 | changeDetection: ChangeDetectionStrategy.OnPush,
|
694 | animations: [
|
695 | trigger('animationState', [
|
696 | transition(':enter', [style({ opacity: 0 }), animate('500ms 100ms', style({ opacity: 1 }))])
|
697 | ])
|
698 | ]
|
699 | },] }
|
700 | ];
|
701 | ChartComponent.propDecorators = {
|
702 | view: [{ type: Input }],
|
703 | showLegend: [{ type: Input }],
|
704 | legendOptions: [{ type: Input }],
|
705 | legendType: [{ type: Input }],
|
706 | activeEntries: [{ type: Input }],
|
707 | animations: [{ type: Input }],
|
708 | legendLabelClick: [{ type: Output }],
|
709 | legendLabelActivate: [{ type: Output }],
|
710 | legendLabelDeactivate: [{ type: Output }]
|
711 | };
|
712 |
|
713 |
|
714 |
|
715 |
|
716 | class VisibilityObserver {
|
717 | constructor(element, zone) {
|
718 | this.element = element;
|
719 | this.zone = zone;
|
720 | this.visible = new EventEmitter();
|
721 | this.isVisible = false;
|
722 | this.runCheck();
|
723 | }
|
724 | destroy() {
|
725 | clearTimeout(this.timeout);
|
726 | }
|
727 | onVisibilityChange() {
|
728 |
|
729 | this.zone.run(() => {
|
730 | this.isVisible = true;
|
731 | this.visible.emit(true);
|
732 | });
|
733 | }
|
734 | runCheck() {
|
735 | const check = () => {
|
736 | if (!this.element) {
|
737 | return;
|
738 | }
|
739 |
|
740 | const { offsetHeight, offsetWidth } = this.element.nativeElement;
|
741 | if (offsetHeight && offsetWidth) {
|
742 | clearTimeout(this.timeout);
|
743 | this.onVisibilityChange();
|
744 | }
|
745 | else {
|
746 | clearTimeout(this.timeout);
|
747 | this.zone.runOutsideAngular(() => {
|
748 | this.timeout = setTimeout(() => check(), 100);
|
749 | });
|
750 | }
|
751 | };
|
752 | this.zone.runOutsideAngular(() => {
|
753 | this.timeout = setTimeout(() => check());
|
754 | });
|
755 | }
|
756 | }
|
757 | VisibilityObserver.decorators = [
|
758 | { type: Directive, args: [{
|
759 | selector: 'visibility-observer'
|
760 | },] }
|
761 | ];
|
762 | VisibilityObserver.ctorParameters = () => [
|
763 | { type: ElementRef },
|
764 | { type: NgZone }
|
765 | ];
|
766 | VisibilityObserver.propDecorators = {
|
767 | visible: [{ type: Output }]
|
768 | };
|
769 |
|
770 | function isDate(value) {
|
771 | return toString.call(value) === '[object Date]';
|
772 | }
|
773 | function isNumber(value) {
|
774 | return typeof value === 'number';
|
775 | }
|
776 |
|
777 | class BaseChartComponent {
|
778 | constructor(chartElement, zone, cd, platformId) {
|
779 | this.chartElement = chartElement;
|
780 | this.zone = zone;
|
781 | this.cd = cd;
|
782 | this.platformId = platformId;
|
783 | this.scheme = 'cool';
|
784 | this.schemeType = ScaleType.Ordinal;
|
785 | this.animations = true;
|
786 | this.select = new EventEmitter();
|
787 | }
|
788 | ngOnInit() {
|
789 | if (isPlatformServer(this.platformId)) {
|
790 | this.animations = false;
|
791 | }
|
792 | }
|
793 | ngAfterViewInit() {
|
794 | this.bindWindowResizeEvent();
|
795 |
|
796 | this.visibilityObserver = new VisibilityObserver(this.chartElement, this.zone);
|
797 | this.visibilityObserver.visible.subscribe(this.update.bind(this));
|
798 | }
|
799 | ngOnDestroy() {
|
800 | this.unbindEvents();
|
801 | if (this.visibilityObserver) {
|
802 | this.visibilityObserver.visible.unsubscribe();
|
803 | this.visibilityObserver.destroy();
|
804 | }
|
805 | }
|
806 | ngOnChanges(changes) {
|
807 | this.update();
|
808 | }
|
809 | update() {
|
810 | if (this.results) {
|
811 | this.results = this.cloneData(this.results);
|
812 | }
|
813 | else {
|
814 | this.results = [];
|
815 | }
|
816 | if (this.view) {
|
817 | this.width = this.view[0];
|
818 | this.height = this.view[1];
|
819 | }
|
820 | else {
|
821 | const dims = this.getContainerDims();
|
822 | if (dims) {
|
823 | this.width = dims.width;
|
824 | this.height = dims.height;
|
825 | }
|
826 | }
|
827 |
|
828 | if (!this.width) {
|
829 | this.width = 600;
|
830 | }
|
831 | if (!this.height) {
|
832 | this.height = 400;
|
833 | }
|
834 | this.width = Math.floor(this.width);
|
835 | this.height = Math.floor(this.height);
|
836 | if (this.cd) {
|
837 | this.cd.markForCheck();
|
838 | }
|
839 | }
|
840 | getContainerDims() {
|
841 | let width;
|
842 | let height;
|
843 | const hostElem = this.chartElement.nativeElement;
|
844 | if (isPlatformBrowser(this.platformId) && hostElem.parentNode !== null) {
|
845 |
|
846 | const dims = hostElem.parentNode.getBoundingClientRect();
|
847 | width = dims.width;
|
848 | height = dims.height;
|
849 | }
|
850 | if (width && height) {
|
851 | return { width, height };
|
852 | }
|
853 | return null;
|
854 | }
|
855 | |
856 |
|
857 |
|
858 |
|
859 | formatDates() {
|
860 | for (let i = 0; i < this.results.length; i++) {
|
861 | const g = this.results[i];
|
862 | g.label = g.name;
|
863 | if (isDate(g.label)) {
|
864 | g.label = g.label.toLocaleDateString();
|
865 | }
|
866 | if (g.series) {
|
867 | for (let j = 0; j < g.series.length; j++) {
|
868 | const d = g.series[j];
|
869 | d.label = d.name;
|
870 | if (isDate(d.label)) {
|
871 | d.label = d.label.toLocaleDateString();
|
872 | }
|
873 | }
|
874 | }
|
875 | }
|
876 | }
|
877 | unbindEvents() {
|
878 | if (this.resizeSubscription) {
|
879 | this.resizeSubscription.unsubscribe();
|
880 | }
|
881 | }
|
882 | bindWindowResizeEvent() {
|
883 | if (!isPlatformBrowser(this.platformId)) {
|
884 | return;
|
885 | }
|
886 | const source = fromEvent(window, 'resize');
|
887 | const subscription = source.pipe(debounceTime(200)).subscribe(e => {
|
888 | this.update();
|
889 | if (this.cd) {
|
890 | this.cd.markForCheck();
|
891 | }
|
892 | });
|
893 | this.resizeSubscription = subscription;
|
894 | }
|
895 | |
896 |
|
897 |
|
898 |
|
899 |
|
900 | cloneData(data) {
|
901 | const results = [];
|
902 | for (const item of data) {
|
903 | const copy = {
|
904 | name: item['name']
|
905 | };
|
906 | if (item['value'] !== undefined) {
|
907 | copy['value'] = item['value'];
|
908 | }
|
909 | if (item['series'] !== undefined) {
|
910 | copy['series'] = [];
|
911 | for (const seriesItem of item['series']) {
|
912 | const seriesItemCopy = Object.assign({}, seriesItem);
|
913 | copy['series'].push(seriesItemCopy);
|
914 | }
|
915 | }
|
916 | if (item['extra'] !== undefined) {
|
917 | copy['extra'] = JSON.parse(JSON.stringify(item['extra']));
|
918 | }
|
919 | results.push(copy);
|
920 | }
|
921 | return results;
|
922 | }
|
923 | }
|
924 | BaseChartComponent.decorators = [
|
925 | { type: Component, args: [{
|
926 | selector: 'base-chart',
|
927 | template: ` <div></div> `
|
928 | },] }
|
929 | ];
|
930 | BaseChartComponent.ctorParameters = () => [
|
931 | { type: ElementRef },
|
932 | { type: NgZone },
|
933 | { type: ChangeDetectorRef },
|
934 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
935 | ];
|
936 | BaseChartComponent.propDecorators = {
|
937 | results: [{ type: Input }],
|
938 | view: [{ type: Input }],
|
939 | scheme: [{ type: Input }],
|
940 | schemeType: [{ type: Input }],
|
941 | customColors: [{ type: Input }],
|
942 | animations: [{ type: Input }],
|
943 | select: [{ type: Output }]
|
944 | };
|
945 |
|
946 | var Orientation;
|
947 | (function (Orientation) {
|
948 | Orientation["Top"] = "top";
|
949 | Orientation["Bottom"] = "bottom";
|
950 | Orientation["Left"] = "left";
|
951 | Orientation["Right"] = "right";
|
952 | })(Orientation || (Orientation = {}));
|
953 |
|
954 | class AxisLabelComponent {
|
955 | constructor(element) {
|
956 | this.textHeight = 25;
|
957 | this.margin = 5;
|
958 | this.element = element.nativeElement;
|
959 | }
|
960 | ngOnChanges(changes) {
|
961 | this.update();
|
962 | }
|
963 | update() {
|
964 | this.strokeWidth = '0.01';
|
965 | this.textAnchor = 'middle';
|
966 | this.transform = '';
|
967 | switch (this.orient) {
|
968 | case Orientation.Top:
|
969 | this.y = this.offset;
|
970 | this.x = this.width / 2;
|
971 | break;
|
972 | case Orientation.Bottom:
|
973 | this.y = this.offset;
|
974 | this.x = this.width / 2;
|
975 | break;
|
976 | case Orientation.Left:
|
977 | this.y = -(this.offset + this.textHeight + this.margin);
|
978 | this.x = -this.height / 2;
|
979 | this.transform = 'rotate(270)';
|
980 | break;
|
981 | case Orientation.Right:
|
982 | this.y = this.offset + this.margin;
|
983 | this.x = -this.height / 2;
|
984 | this.transform = 'rotate(270)';
|
985 | break;
|
986 | default:
|
987 | }
|
988 | }
|
989 | }
|
990 | AxisLabelComponent.decorators = [
|
991 | { type: Component, args: [{
|
992 | selector: 'g[ngx-charts-axis-label]',
|
993 | template: `
|
994 | <svg:text
|
995 | [attr.stroke-width]="strokeWidth"
|
996 | [attr.x]="x"
|
997 | [attr.y]="y"
|
998 | [attr.text-anchor]="textAnchor"
|
999 | [attr.transform]="transform"
|
1000 | >
|
1001 | {{ label }}
|
1002 | </svg:text>
|
1003 | `,
|
1004 | changeDetection: ChangeDetectionStrategy.OnPush
|
1005 | },] }
|
1006 | ];
|
1007 | AxisLabelComponent.ctorParameters = () => [
|
1008 | { type: ElementRef }
|
1009 | ];
|
1010 | AxisLabelComponent.propDecorators = {
|
1011 | orient: [{ type: Input }],
|
1012 | label: [{ type: Input }],
|
1013 | offset: [{ type: Input }],
|
1014 | width: [{ type: Input }],
|
1015 | height: [{ type: Input }]
|
1016 | };
|
1017 |
|
1018 | function trimLabel(s, max = 16) {
|
1019 | if (typeof s !== 'string') {
|
1020 | if (typeof s === 'number') {
|
1021 | return s + '';
|
1022 | }
|
1023 | else {
|
1024 | return '';
|
1025 | }
|
1026 | }
|
1027 | s = s.trim();
|
1028 | if (s.length <= max) {
|
1029 | return s;
|
1030 | }
|
1031 | else {
|
1032 | return `${s.slice(0, max)}...`;
|
1033 | }
|
1034 | }
|
1035 |
|
1036 | function reduceTicks(ticks, maxTicks) {
|
1037 | if (ticks.length > maxTicks) {
|
1038 | const reduced = [];
|
1039 | const modulus = Math.floor(ticks.length / maxTicks);
|
1040 | for (let i = 0; i < ticks.length; i++) {
|
1041 | if (i % modulus === 0) {
|
1042 | reduced.push(ticks[i]);
|
1043 | }
|
1044 | }
|
1045 | ticks = reduced;
|
1046 | }
|
1047 | return ticks;
|
1048 | }
|
1049 |
|
1050 | var TextAnchor;
|
1051 | (function (TextAnchor) {
|
1052 | TextAnchor["Start"] = "start";
|
1053 | TextAnchor["Middle"] = "middle";
|
1054 | TextAnchor["End"] = "end";
|
1055 | })(TextAnchor || (TextAnchor = {}));
|
1056 |
|
1057 | class XAxisTicksComponent {
|
1058 | constructor(platformId) {
|
1059 | this.platformId = platformId;
|
1060 | this.tickArguments = [5];
|
1061 | this.tickStroke = '#ccc';
|
1062 | this.trimTicks = true;
|
1063 | this.maxTickLength = 16;
|
1064 | this.showGridLines = false;
|
1065 | this.rotateTicks = true;
|
1066 | this.dimensionsChanged = new EventEmitter();
|
1067 | this.verticalSpacing = 20;
|
1068 | this.rotateLabels = false;
|
1069 | this.innerTickSize = 6;
|
1070 | this.outerTickSize = 6;
|
1071 | this.tickPadding = 3;
|
1072 | this.textAnchor = TextAnchor.Middle;
|
1073 | this.maxTicksLength = 0;
|
1074 | this.maxAllowedLength = 16;
|
1075 | this.height = 0;
|
1076 | this.approxHeight = 10;
|
1077 | }
|
1078 | ngOnChanges(changes) {
|
1079 | this.update();
|
1080 | }
|
1081 | ngAfterViewInit() {
|
1082 | setTimeout(() => this.updateDims());
|
1083 | }
|
1084 | updateDims() {
|
1085 | if (!isPlatformBrowser(this.platformId)) {
|
1086 |
|
1087 | this.dimensionsChanged.emit({ height: this.approxHeight });
|
1088 | return;
|
1089 | }
|
1090 | const height = parseInt(this.ticksElement.nativeElement.getBoundingClientRect().height, 10);
|
1091 | if (height !== this.height) {
|
1092 | this.height = height;
|
1093 | this.dimensionsChanged.emit({ height: this.height });
|
1094 | setTimeout(() => this.updateDims());
|
1095 | }
|
1096 | }
|
1097 | update() {
|
1098 | const scale = this.scale;
|
1099 | this.ticks = this.getTicks();
|
1100 | if (this.tickFormatting) {
|
1101 | this.tickFormat = this.tickFormatting;
|
1102 | }
|
1103 | else if (scale.tickFormat) {
|
1104 | this.tickFormat = scale.tickFormat.apply(scale, this.tickArguments);
|
1105 | }
|
1106 | else {
|
1107 | this.tickFormat = function (d) {
|
1108 | if (d.constructor.name === 'Date') {
|
1109 | return d.toLocaleDateString();
|
1110 | }
|
1111 | return d.toLocaleString();
|
1112 | };
|
1113 | }
|
1114 | const angle = this.rotateTicks ? this.getRotationAngle(this.ticks) : null;
|
1115 | this.adjustedScale = this.scale.bandwidth
|
1116 | ? function (d) {
|
1117 | return this.scale(d) + this.scale.bandwidth() * 0.5;
|
1118 | }
|
1119 | : this.scale;
|
1120 | this.textTransform = '';
|
1121 | if (angle && angle !== 0) {
|
1122 | this.textTransform = `rotate(${angle})`;
|
1123 | this.textAnchor = TextAnchor.End;
|
1124 | this.verticalSpacing = 10;
|
1125 | }
|
1126 | else {
|
1127 | this.textAnchor = TextAnchor.Middle;
|
1128 | }
|
1129 | setTimeout(() => this.updateDims());
|
1130 | }
|
1131 | getRotationAngle(ticks) {
|
1132 | let angle = 0;
|
1133 | this.maxTicksLength = 0;
|
1134 | for (let i = 0; i < ticks.length; i++) {
|
1135 | const tick = this.tickFormat(ticks[i]).toString();
|
1136 | let tickLength = tick.length;
|
1137 | if (this.trimTicks) {
|
1138 | tickLength = this.tickTrim(tick).length;
|
1139 | }
|
1140 | if (tickLength > this.maxTicksLength) {
|
1141 | this.maxTicksLength = tickLength;
|
1142 | }
|
1143 | }
|
1144 | const len = Math.min(this.maxTicksLength, this.maxAllowedLength);
|
1145 | const charWidth = 7;
|
1146 | const wordWidth = len * charWidth;
|
1147 | let baseWidth = wordWidth;
|
1148 | const maxBaseWidth = Math.floor(this.width / ticks.length);
|
1149 |
|
1150 | while (baseWidth > maxBaseWidth && angle > -90) {
|
1151 | angle -= 30;
|
1152 | baseWidth = Math.cos(angle * (Math.PI / 180)) * wordWidth;
|
1153 | }
|
1154 | this.approxHeight = Math.max(Math.abs(Math.sin(angle * (Math.PI / 180)) * wordWidth), 10);
|
1155 | return angle;
|
1156 | }
|
1157 | getTicks() {
|
1158 | let ticks;
|
1159 | const maxTicks = this.getMaxTicks(20);
|
1160 | const maxScaleTicks = this.getMaxTicks(100);
|
1161 | if (this.tickValues) {
|
1162 | ticks = this.tickValues;
|
1163 | }
|
1164 | else if (this.scale.ticks) {
|
1165 | ticks = this.scale.ticks.apply(this.scale, [maxScaleTicks]);
|
1166 | }
|
1167 | else {
|
1168 | ticks = this.scale.domain();
|
1169 | ticks = reduceTicks(ticks, maxTicks);
|
1170 | }
|
1171 | return ticks;
|
1172 | }
|
1173 | getMaxTicks(tickWidth) {
|
1174 | return Math.floor(this.width / tickWidth);
|
1175 | }
|
1176 | tickTransform(tick) {
|
1177 | return 'translate(' + this.adjustedScale(tick) + ',' + this.verticalSpacing + ')';
|
1178 | }
|
1179 | gridLineTransform() {
|
1180 | return `translate(0,${-this.verticalSpacing - 5})`;
|
1181 | }
|
1182 | tickTrim(label) {
|
1183 | return this.trimTicks ? trimLabel(label, this.maxTickLength) : label;
|
1184 | }
|
1185 | }
|
1186 | XAxisTicksComponent.decorators = [
|
1187 | { type: Component, args: [{
|
1188 | selector: 'g[ngx-charts-x-axis-ticks]',
|
1189 | template: `
|
1190 | <svg:g #ticksel>
|
1191 | <svg:g *ngFor="let tick of ticks" class="tick" [attr.transform]="tickTransform(tick)">
|
1192 | <title>{{ tickFormat(tick) }}</title>
|
1193 | <svg:text
|
1194 | stroke-width="0.01"
|
1195 | [attr.text-anchor]="textAnchor"
|
1196 | [attr.transform]="textTransform"
|
1197 | [style.font-size]="'12px'"
|
1198 | >
|
1199 | {{ tickTrim(tickFormat(tick)) }}
|
1200 | </svg:text>
|
1201 | </svg:g>
|
1202 | </svg:g>
|
1203 |
|
1204 | <svg:g *ngFor="let tick of ticks" [attr.transform]="tickTransform(tick)">
|
1205 | <svg:g *ngIf="showGridLines" [attr.transform]="gridLineTransform()">
|
1206 | <svg:line class="gridline-path gridline-path-vertical" [attr.y1]="-gridLineHeight" y2="0" />
|
1207 | </svg:g>
|
1208 | </svg:g>
|
1209 | `,
|
1210 | changeDetection: ChangeDetectionStrategy.OnPush
|
1211 | },] }
|
1212 | ];
|
1213 | XAxisTicksComponent.ctorParameters = () => [
|
1214 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
1215 | ];
|
1216 | XAxisTicksComponent.propDecorators = {
|
1217 | scale: [{ type: Input }],
|
1218 | orient: [{ type: Input }],
|
1219 | tickArguments: [{ type: Input }],
|
1220 | tickValues: [{ type: Input }],
|
1221 | tickStroke: [{ type: Input }],
|
1222 | trimTicks: [{ type: Input }],
|
1223 | maxTickLength: [{ type: Input }],
|
1224 | tickFormatting: [{ type: Input }],
|
1225 | showGridLines: [{ type: Input }],
|
1226 | gridLineHeight: [{ type: Input }],
|
1227 | width: [{ type: Input }],
|
1228 | rotateTicks: [{ type: Input }],
|
1229 | dimensionsChanged: [{ type: Output }],
|
1230 | ticksElement: [{ type: ViewChild, args: ['ticksel',] }]
|
1231 | };
|
1232 |
|
1233 | class XAxisComponent {
|
1234 | constructor() {
|
1235 | this.rotateTicks = true;
|
1236 | this.showGridLines = false;
|
1237 | this.xOrient = Orientation.Bottom;
|
1238 | this.xAxisOffset = 0;
|
1239 | this.dimensionsChanged = new EventEmitter();
|
1240 | this.xAxisClassName = 'x axis';
|
1241 | this.labelOffset = 0;
|
1242 | this.fill = 'none';
|
1243 | this.stroke = 'stroke';
|
1244 | this.tickStroke = '#ccc';
|
1245 | this.strokeWidth = 'none';
|
1246 | this.padding = 5;
|
1247 | this.orientation = Orientation;
|
1248 | }
|
1249 | ngOnChanges(changes) {
|
1250 | this.update();
|
1251 | }
|
1252 | update() {
|
1253 | this.transform = `translate(0,${this.xAxisOffset + this.padding + this.dims.height})`;
|
1254 | if (typeof this.xAxisTickCount !== 'undefined') {
|
1255 | this.tickArguments = [this.xAxisTickCount];
|
1256 | }
|
1257 | }
|
1258 | emitTicksHeight({ height }) {
|
1259 | const newLabelOffset = height + 25 + 5;
|
1260 | if (newLabelOffset !== this.labelOffset) {
|
1261 | this.labelOffset = newLabelOffset;
|
1262 | setTimeout(() => {
|
1263 | this.dimensionsChanged.emit({ height });
|
1264 | }, 0);
|
1265 | }
|
1266 | }
|
1267 | }
|
1268 | XAxisComponent.decorators = [
|
1269 | { type: Component, args: [{
|
1270 | selector: 'g[ngx-charts-x-axis]',
|
1271 | template: `
|
1272 | <svg:g [attr.class]="xAxisClassName" [attr.transform]="transform">
|
1273 | <svg:g
|
1274 | ngx-charts-x-axis-ticks
|
1275 | *ngIf="xScale"
|
1276 | [trimTicks]="trimTicks"
|
1277 | [rotateTicks]="rotateTicks"
|
1278 | [maxTickLength]="maxTickLength"
|
1279 | [tickFormatting]="tickFormatting"
|
1280 | [tickArguments]="tickArguments"
|
1281 | [tickStroke]="tickStroke"
|
1282 | [scale]="xScale"
|
1283 | [orient]="xOrient"
|
1284 | [showGridLines]="showGridLines"
|
1285 | [gridLineHeight]="dims.height"
|
1286 | [width]="dims.width"
|
1287 | [tickValues]="ticks"
|
1288 | (dimensionsChanged)="emitTicksHeight($event)"
|
1289 | />
|
1290 | <svg:g
|
1291 | ngx-charts-axis-label
|
1292 | *ngIf="showLabel"
|
1293 | [label]="labelText"
|
1294 | [offset]="labelOffset"
|
1295 | [orient]="orientation.Bottom"
|
1296 | [height]="dims.height"
|
1297 | [width]="dims.width"
|
1298 | ></svg:g>
|
1299 | </svg:g>
|
1300 | `,
|
1301 | changeDetection: ChangeDetectionStrategy.OnPush
|
1302 | },] }
|
1303 | ];
|
1304 | XAxisComponent.propDecorators = {
|
1305 | xScale: [{ type: Input }],
|
1306 | dims: [{ type: Input }],
|
1307 | trimTicks: [{ type: Input }],
|
1308 | rotateTicks: [{ type: Input }],
|
1309 | maxTickLength: [{ type: Input }],
|
1310 | tickFormatting: [{ type: Input }],
|
1311 | showGridLines: [{ type: Input }],
|
1312 | showLabel: [{ type: Input }],
|
1313 | labelText: [{ type: Input }],
|
1314 | ticks: [{ type: Input }],
|
1315 | xAxisTickCount: [{ type: Input }],
|
1316 | xOrient: [{ type: Input }],
|
1317 | xAxisOffset: [{ type: Input }],
|
1318 | dimensionsChanged: [{ type: Output }],
|
1319 | ticksComponent: [{ type: ViewChild, args: [XAxisTicksComponent,] }]
|
1320 | };
|
1321 |
|
1322 |
|
1323 |
|
1324 |
|
1325 |
|
1326 |
|
1327 |
|
1328 | function roundedRect(x, y, w, h, r, [tl, tr, bl, br]) {
|
1329 | let retval = '';
|
1330 | w = Math.floor(w);
|
1331 | h = Math.floor(h);
|
1332 | w = w === 0 ? 1 : w;
|
1333 | h = h === 0 ? 1 : h;
|
1334 | retval = `M${[x + r, y]}`;
|
1335 | retval += `h${w - 2 * r}`;
|
1336 | if (tr) {
|
1337 | retval += `a${[r, r]} 0 0 1 ${[r, r]}`;
|
1338 | }
|
1339 | else {
|
1340 | retval += `h${r}v${r}`;
|
1341 | }
|
1342 | retval += `v${h - 2 * r}`;
|
1343 | if (br) {
|
1344 | retval += `a${[r, r]} 0 0 1 ${[-r, r]}`;
|
1345 | }
|
1346 | else {
|
1347 | retval += `v${r}h${-r}`;
|
1348 | }
|
1349 | retval += `h${2 * r - w}`;
|
1350 | if (bl) {
|
1351 | retval += `a${[r, r]} 0 0 1 ${[-r, -r]}`;
|
1352 | }
|
1353 | else {
|
1354 | retval += `h${-r}v${-r}`;
|
1355 | }
|
1356 | retval += `v${2 * r - h}`;
|
1357 | if (tl) {
|
1358 | retval += `a${[r, r]} 0 0 1 ${[r, -r]}`;
|
1359 | }
|
1360 | else {
|
1361 | retval += `v${-r}h${r}`;
|
1362 | }
|
1363 | retval += `z`;
|
1364 | return retval;
|
1365 | }
|
1366 |
|
1367 | class YAxisTicksComponent {
|
1368 | constructor(platformId) {
|
1369 | this.platformId = platformId;
|
1370 | this.tickArguments = [5];
|
1371 | this.tickStroke = '#ccc';
|
1372 | this.trimTicks = true;
|
1373 | this.maxTickLength = 16;
|
1374 | this.showGridLines = false;
|
1375 | this.showRefLabels = false;
|
1376 | this.showRefLines = false;
|
1377 | this.dimensionsChanged = new EventEmitter();
|
1378 | this.innerTickSize = 6;
|
1379 | this.tickPadding = 3;
|
1380 | this.verticalSpacing = 20;
|
1381 | this.textAnchor = TextAnchor.Middle;
|
1382 | this.width = 0;
|
1383 | this.outerTickSize = 6;
|
1384 | this.rotateLabels = false;
|
1385 | this.referenceLineLength = 0;
|
1386 | this.Orientation = Orientation;
|
1387 | }
|
1388 | ngOnChanges(changes) {
|
1389 | this.update();
|
1390 | }
|
1391 | ngAfterViewInit() {
|
1392 | setTimeout(() => this.updateDims());
|
1393 | }
|
1394 | updateDims() {
|
1395 | if (!isPlatformBrowser(this.platformId)) {
|
1396 |
|
1397 | this.width = this.getApproximateAxisWidth();
|
1398 | this.dimensionsChanged.emit({ width: this.width });
|
1399 | return;
|
1400 | }
|
1401 | const width = parseInt(this.ticksElement.nativeElement.getBoundingClientRect().width, 10);
|
1402 | if (width !== this.width) {
|
1403 | this.width = width;
|
1404 | this.dimensionsChanged.emit({ width });
|
1405 | setTimeout(() => this.updateDims());
|
1406 | }
|
1407 | }
|
1408 | update() {
|
1409 | let scale;
|
1410 | const sign = this.orient === Orientation.Top || this.orient === Orientation.Right ? -1 : 1;
|
1411 | this.tickSpacing = Math.max(this.innerTickSize, 0) + this.tickPadding;
|
1412 | scale = this.scale;
|
1413 | this.ticks = this.getTicks();
|
1414 | if (this.tickFormatting) {
|
1415 | this.tickFormat = this.tickFormatting;
|
1416 | }
|
1417 | else if (scale.tickFormat) {
|
1418 | this.tickFormat = scale.tickFormat.apply(scale, this.tickArguments);
|
1419 | }
|
1420 | else {
|
1421 | this.tickFormat = function (d) {
|
1422 | if (d.constructor.name === 'Date') {
|
1423 | return d.toLocaleDateString();
|
1424 | }
|
1425 | return d.toLocaleString();
|
1426 | };
|
1427 | }
|
1428 | this.adjustedScale = scale.bandwidth
|
1429 | ? function (d) {
|
1430 | return scale(d) + scale.bandwidth() * 0.5;
|
1431 | }
|
1432 | : scale;
|
1433 | if (this.showRefLines && this.referenceLines) {
|
1434 | this.setReferencelines();
|
1435 | }
|
1436 | switch (this.orient) {
|
1437 | case Orientation.Top:
|
1438 | this.transform = function (tick) {
|
1439 | return 'translate(' + this.adjustedScale(tick) + ',0)';
|
1440 | };
|
1441 | this.textAnchor = TextAnchor.Middle;
|
1442 | this.y2 = this.innerTickSize * sign;
|
1443 | this.y1 = this.tickSpacing * sign;
|
1444 | this.dy = sign < 0 ? '0em' : '.71em';
|
1445 | break;
|
1446 | case Orientation.Bottom:
|
1447 | this.transform = function (tick) {
|
1448 | return 'translate(' + this.adjustedScale(tick) + ',0)';
|
1449 | };
|
1450 | this.textAnchor = TextAnchor.Middle;
|
1451 | this.y2 = this.innerTickSize * sign;
|
1452 | this.y1 = this.tickSpacing * sign;
|
1453 | this.dy = sign < 0 ? '0em' : '.71em';
|
1454 | break;
|
1455 | case Orientation.Left:
|
1456 | this.transform = function (tick) {
|
1457 | return 'translate(0,' + this.adjustedScale(tick) + ')';
|
1458 | };
|
1459 | this.textAnchor = TextAnchor.End;
|
1460 | this.x2 = this.innerTickSize * -sign;
|
1461 | this.x1 = this.tickSpacing * -sign;
|
1462 | this.dy = '.32em';
|
1463 | break;
|
1464 | case Orientation.Right:
|
1465 | this.transform = function (tick) {
|
1466 | return 'translate(0,' + this.adjustedScale(tick) + ')';
|
1467 | };
|
1468 | this.textAnchor = TextAnchor.Start;
|
1469 | this.x2 = this.innerTickSize * -sign;
|
1470 | this.x1 = this.tickSpacing * -sign;
|
1471 | this.dy = '.32em';
|
1472 | break;
|
1473 | default:
|
1474 | }
|
1475 | setTimeout(() => this.updateDims());
|
1476 | }
|
1477 | setReferencelines() {
|
1478 | this.refMin = this.adjustedScale(Math.min.apply(null, this.referenceLines.map(item => item.value)));
|
1479 | this.refMax = this.adjustedScale(Math.max.apply(null, this.referenceLines.map(item => item.value)));
|
1480 | this.referenceLineLength = this.referenceLines.length;
|
1481 | this.referenceAreaPath = roundedRect(0, this.refMax, this.gridLineWidth, this.refMin - this.refMax, 0, [
|
1482 | false,
|
1483 | false,
|
1484 | false,
|
1485 | false
|
1486 | ]);
|
1487 | }
|
1488 | getTicks() {
|
1489 | let ticks;
|
1490 | const maxTicks = this.getMaxTicks(20);
|
1491 | const maxScaleTicks = this.getMaxTicks(50);
|
1492 | if (this.tickValues) {
|
1493 | ticks = this.tickValues;
|
1494 | }
|
1495 | else if (this.scale.ticks) {
|
1496 | ticks = this.scale.ticks.apply(this.scale, [maxScaleTicks]);
|
1497 | }
|
1498 | else {
|
1499 | ticks = this.scale.domain();
|
1500 | ticks = reduceTicks(ticks, maxTicks);
|
1501 | }
|
1502 | return ticks;
|
1503 | }
|
1504 | getMaxTicks(tickHeight) {
|
1505 | return Math.floor(this.height / tickHeight);
|
1506 | }
|
1507 | tickTransform(tick) {
|
1508 | return `translate(${this.adjustedScale(tick)},${this.verticalSpacing})`;
|
1509 | }
|
1510 | gridLineTransform() {
|
1511 | return `translate(5,0)`;
|
1512 | }
|
1513 | tickTrim(label) {
|
1514 | return this.trimTicks ? trimLabel(label, this.maxTickLength) : label;
|
1515 | }
|
1516 | getApproximateAxisWidth() {
|
1517 | const maxChars = Math.max(...this.ticks.map(t => this.tickTrim(this.tickFormat(t)).length));
|
1518 | const charWidth = 7;
|
1519 | return maxChars * charWidth;
|
1520 | }
|
1521 | }
|
1522 | YAxisTicksComponent.decorators = [
|
1523 | { type: Component, args: [{
|
1524 | selector: 'g[ngx-charts-y-axis-ticks]',
|
1525 | template: `
|
1526 | <svg:g #ticksel>
|
1527 | <svg:g *ngFor="let tick of ticks" class="tick" [attr.transform]="transform(tick)">
|
1528 | <title>{{ tickFormat(tick) }}</title>
|
1529 | <svg:text
|
1530 | stroke-width="0.01"
|
1531 | [attr.dy]="dy"
|
1532 | [attr.x]="x1"
|
1533 | [attr.y]="y1"
|
1534 | [attr.text-anchor]="textAnchor"
|
1535 | [style.font-size]="'12px'"
|
1536 | >
|
1537 | {{ tickTrim(tickFormat(tick)) }}
|
1538 | </svg:text>
|
1539 | </svg:g>
|
1540 | </svg:g>
|
1541 |
|
1542 | <svg:path
|
1543 | *ngIf="referenceLineLength > 1 && refMax && refMin && showRefLines"
|
1544 | class="reference-area"
|
1545 | [attr.d]="referenceAreaPath"
|
1546 | [attr.transform]="gridLineTransform()"
|
1547 | />
|
1548 | <svg:g *ngFor="let tick of ticks" [attr.transform]="transform(tick)">
|
1549 | <svg:g *ngIf="showGridLines" [attr.transform]="gridLineTransform()">
|
1550 | <svg:line
|
1551 | *ngIf="orient === Orientation.Left"
|
1552 | class="gridline-path gridline-path-horizontal"
|
1553 | x1="0"
|
1554 | [attr.x2]="gridLineWidth"
|
1555 | />
|
1556 | <svg:line
|
1557 | *ngIf="orient === Orientation.Right"
|
1558 | class="gridline-path gridline-path-horizontal"
|
1559 | x1="0"
|
1560 | [attr.x2]="-gridLineWidth"
|
1561 | />
|
1562 | </svg:g>
|
1563 | </svg:g>
|
1564 |
|
1565 | <svg:g *ngFor="let refLine of referenceLines">
|
1566 | <svg:g *ngIf="showRefLines" [attr.transform]="transform(refLine.value)">
|
1567 | <svg:line
|
1568 | class="refline-path gridline-path-horizontal"
|
1569 | x1="0"
|
1570 | [attr.x2]="gridLineWidth"
|
1571 | [attr.transform]="gridLineTransform()"
|
1572 | />
|
1573 | <svg:g *ngIf="showRefLabels">
|
1574 | <title>{{ tickTrim(tickFormat(refLine.value)) }}</title>
|
1575 | <svg:text
|
1576 | class="refline-label"
|
1577 | [attr.dy]="dy"
|
1578 | [attr.y]="-6"
|
1579 | [attr.x]="gridLineWidth"
|
1580 | [attr.text-anchor]="textAnchor"
|
1581 | >
|
1582 | {{ refLine.name }}
|
1583 | </svg:text>
|
1584 | </svg:g>
|
1585 | </svg:g>
|
1586 | </svg:g>
|
1587 | `,
|
1588 | changeDetection: ChangeDetectionStrategy.OnPush
|
1589 | },] }
|
1590 | ];
|
1591 | YAxisTicksComponent.ctorParameters = () => [
|
1592 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
1593 | ];
|
1594 | YAxisTicksComponent.propDecorators = {
|
1595 | scale: [{ type: Input }],
|
1596 | orient: [{ type: Input }],
|
1597 | tickArguments: [{ type: Input }],
|
1598 | tickValues: [{ type: Input }],
|
1599 | tickStroke: [{ type: Input }],
|
1600 | trimTicks: [{ type: Input }],
|
1601 | maxTickLength: [{ type: Input }],
|
1602 | tickFormatting: [{ type: Input }],
|
1603 | showGridLines: [{ type: Input }],
|
1604 | gridLineWidth: [{ type: Input }],
|
1605 | height: [{ type: Input }],
|
1606 | referenceLines: [{ type: Input }],
|
1607 | showRefLabels: [{ type: Input }],
|
1608 | showRefLines: [{ type: Input }],
|
1609 | dimensionsChanged: [{ type: Output }],
|
1610 | ticksElement: [{ type: ViewChild, args: ['ticksel',] }]
|
1611 | };
|
1612 |
|
1613 | class YAxisComponent {
|
1614 | constructor() {
|
1615 | this.showGridLines = false;
|
1616 | this.yOrient = Orientation.Left;
|
1617 | this.yAxisOffset = 0;
|
1618 | this.dimensionsChanged = new EventEmitter();
|
1619 | this.yAxisClassName = 'y axis';
|
1620 | this.labelOffset = 15;
|
1621 | this.fill = 'none';
|
1622 | this.stroke = '#CCC';
|
1623 | this.tickStroke = '#CCC';
|
1624 | this.strokeWidth = 1;
|
1625 | this.padding = 5;
|
1626 | }
|
1627 | ngOnChanges(changes) {
|
1628 | this.update();
|
1629 | }
|
1630 | update() {
|
1631 | this.offset = -(this.yAxisOffset + this.padding);
|
1632 | if (this.yOrient === Orientation.Right) {
|
1633 | this.labelOffset = 65;
|
1634 | this.transform = `translate(${this.offset + this.dims.width} , 0)`;
|
1635 | }
|
1636 | else {
|
1637 | this.offset = this.offset;
|
1638 | this.transform = `translate(${this.offset} , 0)`;
|
1639 | }
|
1640 | if (this.yAxisTickCount !== undefined) {
|
1641 | this.tickArguments = [this.yAxisTickCount];
|
1642 | }
|
1643 | }
|
1644 | emitTicksWidth({ width }) {
|
1645 | if (width !== this.labelOffset && this.yOrient === Orientation.Right) {
|
1646 | this.labelOffset = width + this.labelOffset;
|
1647 | setTimeout(() => {
|
1648 | this.dimensionsChanged.emit({ width });
|
1649 | }, 0);
|
1650 | }
|
1651 | else if (width !== this.labelOffset) {
|
1652 | this.labelOffset = width;
|
1653 | setTimeout(() => {
|
1654 | this.dimensionsChanged.emit({ width });
|
1655 | }, 0);
|
1656 | }
|
1657 | }
|
1658 | }
|
1659 | YAxisComponent.decorators = [
|
1660 | { type: Component, args: [{
|
1661 | selector: 'g[ngx-charts-y-axis]',
|
1662 | template: `
|
1663 | <svg:g [attr.class]="yAxisClassName" [attr.transform]="transform">
|
1664 | <svg:g
|
1665 | ngx-charts-y-axis-ticks
|
1666 | *ngIf="yScale"
|
1667 | [trimTicks]="trimTicks"
|
1668 | [maxTickLength]="maxTickLength"
|
1669 | [tickFormatting]="tickFormatting"
|
1670 | [tickArguments]="tickArguments"
|
1671 | [tickValues]="ticks"
|
1672 | [tickStroke]="tickStroke"
|
1673 | [scale]="yScale"
|
1674 | [orient]="yOrient"
|
1675 | [showGridLines]="showGridLines"
|
1676 | [gridLineWidth]="dims.width"
|
1677 | [referenceLines]="referenceLines"
|
1678 | [showRefLines]="showRefLines"
|
1679 | [showRefLabels]="showRefLabels"
|
1680 | [height]="dims.height"
|
1681 | (dimensionsChanged)="emitTicksWidth($event)"
|
1682 | />
|
1683 |
|
1684 | <svg:g
|
1685 | ngx-charts-axis-label
|
1686 | *ngIf="showLabel"
|
1687 | [label]="labelText"
|
1688 | [offset]="labelOffset"
|
1689 | [orient]="yOrient"
|
1690 | [height]="dims.height"
|
1691 | [width]="dims.width"
|
1692 | ></svg:g>
|
1693 | </svg:g>
|
1694 | `,
|
1695 | changeDetection: ChangeDetectionStrategy.OnPush
|
1696 | },] }
|
1697 | ];
|
1698 | YAxisComponent.propDecorators = {
|
1699 | yScale: [{ type: Input }],
|
1700 | dims: [{ type: Input }],
|
1701 | trimTicks: [{ type: Input }],
|
1702 | maxTickLength: [{ type: Input }],
|
1703 | tickFormatting: [{ type: Input }],
|
1704 | ticks: [{ type: Input }],
|
1705 | showGridLines: [{ type: Input }],
|
1706 | showLabel: [{ type: Input }],
|
1707 | labelText: [{ type: Input }],
|
1708 | yAxisTickCount: [{ type: Input }],
|
1709 | yOrient: [{ type: Input }],
|
1710 | referenceLines: [{ type: Input }],
|
1711 | showRefLines: [{ type: Input }],
|
1712 | showRefLabels: [{ type: Input }],
|
1713 | yAxisOffset: [{ type: Input }],
|
1714 | dimensionsChanged: [{ type: Output }],
|
1715 | ticksComponent: [{ type: ViewChild, args: [YAxisTicksComponent,] }]
|
1716 | };
|
1717 |
|
1718 | class AxesModule {
|
1719 | }
|
1720 | AxesModule.decorators = [
|
1721 | { type: NgModule, args: [{
|
1722 | imports: [CommonModule],
|
1723 | declarations: [AxisLabelComponent, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent],
|
1724 | exports: [AxisLabelComponent, XAxisComponent, XAxisTicksComponent, YAxisComponent, YAxisTicksComponent]
|
1725 | },] }
|
1726 | ];
|
1727 |
|
1728 | var StyleTypes;
|
1729 | (function (StyleTypes) {
|
1730 | StyleTypes["popover"] = "popover";
|
1731 | StyleTypes["tooltip"] = "tooltip";
|
1732 | })(StyleTypes || (StyleTypes = {}));
|
1733 |
|
1734 | var ShowTypes;
|
1735 | (function (ShowTypes) {
|
1736 | ShowTypes[ShowTypes["all"] = 'all'] = "all";
|
1737 | ShowTypes[ShowTypes["focus"] = 'focus'] = "focus";
|
1738 | ShowTypes[ShowTypes["mouseover"] = 'mouseover'] = "mouseover";
|
1739 | })(ShowTypes || (ShowTypes = {}));
|
1740 |
|
1741 | class TooltipDirective {
|
1742 | constructor(tooltipService, viewContainerRef, renderer) {
|
1743 | this.tooltipService = tooltipService;
|
1744 | this.viewContainerRef = viewContainerRef;
|
1745 | this.renderer = renderer;
|
1746 | this.tooltipCssClass = '';
|
1747 | this.tooltipAppendToBody = true;
|
1748 | this.tooltipSpacing = 10;
|
1749 | this.tooltipDisabled = false;
|
1750 | this.tooltipShowCaret = true;
|
1751 | this.tooltipPlacement = PlacementTypes.Top;
|
1752 | this.tooltipAlignment = PlacementTypes.Center;
|
1753 | this.tooltipType = StyleTypes.popover;
|
1754 | this.tooltipCloseOnClickOutside = true;
|
1755 | this.tooltipCloseOnMouseLeave = true;
|
1756 | this.tooltipHideTimeout = 300;
|
1757 | this.tooltipShowTimeout = 100;
|
1758 | this.tooltipShowEvent = ShowTypes.all;
|
1759 | this.tooltipImmediateExit = false;
|
1760 | this.show = new EventEmitter();
|
1761 | this.hide = new EventEmitter();
|
1762 | }
|
1763 | get listensForFocus() {
|
1764 | return this.tooltipShowEvent === ShowTypes.all || this.tooltipShowEvent === ShowTypes.focus;
|
1765 | }
|
1766 | get listensForHover() {
|
1767 | return this.tooltipShowEvent === ShowTypes.all || this.tooltipShowEvent === ShowTypes.mouseover;
|
1768 | }
|
1769 | ngOnDestroy() {
|
1770 | this.hideTooltip(true);
|
1771 | }
|
1772 | onFocus() {
|
1773 | if (this.listensForFocus) {
|
1774 | this.showTooltip();
|
1775 | }
|
1776 | }
|
1777 | onBlur() {
|
1778 | if (this.listensForFocus) {
|
1779 | this.hideTooltip(true);
|
1780 | }
|
1781 | }
|
1782 | onMouseEnter() {
|
1783 | if (this.listensForHover) {
|
1784 | this.showTooltip();
|
1785 | }
|
1786 | }
|
1787 | onMouseLeave(target) {
|
1788 | if (this.listensForHover && this.tooltipCloseOnMouseLeave) {
|
1789 | clearTimeout(this.timeout);
|
1790 | if (this.component) {
|
1791 | const contentDom = this.component.instance.element.nativeElement;
|
1792 | const contains = contentDom.contains(target);
|
1793 | if (contains)
|
1794 | return;
|
1795 | }
|
1796 | this.hideTooltip(this.tooltipImmediateExit);
|
1797 | }
|
1798 | }
|
1799 | onMouseClick() {
|
1800 | if (this.listensForHover) {
|
1801 | this.hideTooltip(true);
|
1802 | }
|
1803 | }
|
1804 | showTooltip(immediate) {
|
1805 | if (this.component || this.tooltipDisabled)
|
1806 | return;
|
1807 | const time = immediate
|
1808 | ? 0
|
1809 | : this.tooltipShowTimeout + (navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) ? 300 : 0);
|
1810 | clearTimeout(this.timeout);
|
1811 | this.timeout = setTimeout(() => {
|
1812 | this.tooltipService.destroyAll();
|
1813 | const options = this.createBoundOptions();
|
1814 | this.component = this.tooltipService.create(options);
|
1815 |
|
1816 | setTimeout(() => {
|
1817 | if (this.component) {
|
1818 | this.addHideListeners(this.component.instance.element.nativeElement);
|
1819 | }
|
1820 | }, 10);
|
1821 | this.show.emit(true);
|
1822 | }, time);
|
1823 | }
|
1824 | addHideListeners(tooltip) {
|
1825 |
|
1826 | this.mouseEnterContentEvent = this.renderer.listen(tooltip, 'mouseenter', () => {
|
1827 | clearTimeout(this.timeout);
|
1828 | });
|
1829 |
|
1830 | if (this.tooltipCloseOnMouseLeave) {
|
1831 | this.mouseLeaveContentEvent = this.renderer.listen(tooltip, 'mouseleave', () => {
|
1832 | this.hideTooltip(this.tooltipImmediateExit);
|
1833 | });
|
1834 | }
|
1835 |
|
1836 | if (this.tooltipCloseOnClickOutside) {
|
1837 | this.documentClickEvent = this.renderer.listen('window', 'click', event => {
|
1838 | const contains = tooltip.contains(event.target);
|
1839 | if (!contains)
|
1840 | this.hideTooltip();
|
1841 | });
|
1842 | }
|
1843 | }
|
1844 | hideTooltip(immediate = false) {
|
1845 | if (!this.component)
|
1846 | return;
|
1847 | const destroyFn = () => {
|
1848 |
|
1849 | if (this.mouseLeaveContentEvent)
|
1850 | this.mouseLeaveContentEvent();
|
1851 | if (this.mouseEnterContentEvent)
|
1852 | this.mouseEnterContentEvent();
|
1853 | if (this.documentClickEvent)
|
1854 | this.documentClickEvent();
|
1855 |
|
1856 | this.hide.emit(true);
|
1857 |
|
1858 | this.tooltipService.destroy(this.component);
|
1859 | this.component = undefined;
|
1860 | };
|
1861 | clearTimeout(this.timeout);
|
1862 | if (!immediate) {
|
1863 | this.timeout = setTimeout(destroyFn, this.tooltipHideTimeout);
|
1864 | }
|
1865 | else {
|
1866 | destroyFn();
|
1867 | }
|
1868 | }
|
1869 | createBoundOptions() {
|
1870 | return {
|
1871 | title: this.tooltipTitle,
|
1872 | template: this.tooltipTemplate,
|
1873 | host: this.viewContainerRef.element,
|
1874 | placement: this.tooltipPlacement,
|
1875 | alignment: this.tooltipAlignment,
|
1876 | type: this.tooltipType,
|
1877 | showCaret: this.tooltipShowCaret,
|
1878 | cssClass: this.tooltipCssClass,
|
1879 | spacing: this.tooltipSpacing,
|
1880 | context: this.tooltipContext
|
1881 | };
|
1882 | }
|
1883 | }
|
1884 | TooltipDirective.decorators = [
|
1885 | { type: Directive, args: [{ selector: '[ngx-tooltip]' },] }
|
1886 | ];
|
1887 | TooltipDirective.ctorParameters = () => [
|
1888 | { type: TooltipService },
|
1889 | { type: ViewContainerRef },
|
1890 | { type: Renderer2 }
|
1891 | ];
|
1892 | TooltipDirective.propDecorators = {
|
1893 | tooltipCssClass: [{ type: Input }],
|
1894 | tooltipTitle: [{ type: Input }],
|
1895 | tooltipAppendToBody: [{ type: Input }],
|
1896 | tooltipSpacing: [{ type: Input }],
|
1897 | tooltipDisabled: [{ type: Input }],
|
1898 | tooltipShowCaret: [{ type: Input }],
|
1899 | tooltipPlacement: [{ type: Input }],
|
1900 | tooltipAlignment: [{ type: Input }],
|
1901 | tooltipType: [{ type: Input }],
|
1902 | tooltipCloseOnClickOutside: [{ type: Input }],
|
1903 | tooltipCloseOnMouseLeave: [{ type: Input }],
|
1904 | tooltipHideTimeout: [{ type: Input }],
|
1905 | tooltipShowTimeout: [{ type: Input }],
|
1906 | tooltipTemplate: [{ type: Input }],
|
1907 | tooltipShowEvent: [{ type: Input }],
|
1908 | tooltipContext: [{ type: Input }],
|
1909 | tooltipImmediateExit: [{ type: Input }],
|
1910 | show: [{ type: Output }],
|
1911 | hide: [{ type: Output }],
|
1912 | onFocus: [{ type: HostListener, args: ['focusin',] }],
|
1913 | onBlur: [{ type: HostListener, args: ['blur',] }],
|
1914 | onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
1915 | onMouseLeave: [{ type: HostListener, args: ['mouseleave', ['$event.target'],] }],
|
1916 | onMouseClick: [{ type: HostListener, args: ['click',] }]
|
1917 | };
|
1918 |
|
1919 | class TooltipModule {
|
1920 | }
|
1921 | TooltipModule.decorators = [
|
1922 | { type: NgModule, args: [{
|
1923 | declarations: [TooltipContentComponent, TooltipDirective],
|
1924 | providers: [InjectionService, TooltipService],
|
1925 | exports: [TooltipContentComponent, TooltipDirective],
|
1926 | imports: [CommonModule],
|
1927 | entryComponents: [TooltipContentComponent]
|
1928 | },] }
|
1929 | ];
|
1930 |
|
1931 |
|
1932 |
|
1933 |
|
1934 |
|
1935 |
|
1936 | function formatLabel(label) {
|
1937 | if (label instanceof Date) {
|
1938 | label = label.toLocaleDateString();
|
1939 | }
|
1940 | else {
|
1941 | label = label.toLocaleString();
|
1942 | }
|
1943 | return label;
|
1944 | }
|
1945 |
|
1946 |
|
1947 |
|
1948 |
|
1949 |
|
1950 | function escapeLabel(label) {
|
1951 | return label.toLocaleString().replace(/[&'`"<>]/g, match => {
|
1952 | return {
|
1953 | '&': '&',
|
1954 |
|
1955 | "'": ''',
|
1956 | '`': '`',
|
1957 | '"': '"',
|
1958 | '<': '<',
|
1959 | '>': '>'
|
1960 | }[match];
|
1961 | });
|
1962 | }
|
1963 |
|
1964 | const cache = {};
|
1965 |
|
1966 |
|
1967 |
|
1968 |
|
1969 |
|
1970 |
|
1971 |
|
1972 |
|
1973 |
|
1974 |
|
1975 | function id() {
|
1976 | let newId = ('0000' + ((Math.random() * Math.pow(36, 4)) << 0).toString(36)).slice(-4);
|
1977 |
|
1978 | newId = `a${newId}`;
|
1979 |
|
1980 | if (!cache[newId]) {
|
1981 | cache[newId] = true;
|
1982 | return newId;
|
1983 | }
|
1984 | return id();
|
1985 | }
|
1986 |
|
1987 | var BarOrientation;
|
1988 | (function (BarOrientation) {
|
1989 | BarOrientation["Vertical"] = "vertical";
|
1990 | BarOrientation["Horizontal"] = "horizontal";
|
1991 | })(BarOrientation || (BarOrientation = {}));
|
1992 |
|
1993 | var SeriesType;
|
1994 | (function (SeriesType) {
|
1995 | SeriesType["Standard"] = "standard";
|
1996 | SeriesType["Stacked"] = "stacked";
|
1997 | })(SeriesType || (SeriesType = {}));
|
1998 | class CircleSeriesComponent {
|
1999 | constructor() {
|
2000 | this.type = SeriesType.Standard;
|
2001 | this.tooltipDisabled = false;
|
2002 | this.select = new EventEmitter();
|
2003 | this.activate = new EventEmitter();
|
2004 | this.deactivate = new EventEmitter();
|
2005 | this.barVisible = false;
|
2006 | this.barOrientation = BarOrientation;
|
2007 | this.placementTypes = PlacementTypes;
|
2008 | this.styleTypes = StyleTypes;
|
2009 | }
|
2010 | ngOnInit() {
|
2011 | this.gradientId = 'grad' + id().toString();
|
2012 | this.gradientFill = `url(#${this.gradientId})`;
|
2013 | }
|
2014 | ngOnChanges() {
|
2015 | this.update();
|
2016 | }
|
2017 | update() {
|
2018 | this.circle = this.getActiveCircle();
|
2019 | }
|
2020 | getActiveCircle() {
|
2021 | const indexActiveDataPoint = this.data.series.findIndex(d => {
|
2022 | const label = d.name;
|
2023 | return label && this.visibleValue && label.toString() === this.visibleValue.toString() && d.value !== undefined;
|
2024 | });
|
2025 | if (indexActiveDataPoint === -1) {
|
2026 |
|
2027 | return undefined;
|
2028 | }
|
2029 | return this.mapDataPointToCircle(this.data.series[indexActiveDataPoint], indexActiveDataPoint);
|
2030 | }
|
2031 | mapDataPointToCircle(d, i) {
|
2032 | const seriesName = this.data.name;
|
2033 | const value = d.value;
|
2034 | const label = d.name;
|
2035 | const tooltipLabel = formatLabel(label);
|
2036 | let cx;
|
2037 | if (this.scaleType === ScaleType.Time) {
|
2038 | cx = this.xScale(label);
|
2039 | }
|
2040 | else if (this.scaleType === ScaleType.Linear) {
|
2041 | cx = this.xScale(Number(label));
|
2042 | }
|
2043 | else {
|
2044 | cx = this.xScale(label);
|
2045 | }
|
2046 | const cy = this.yScale(this.type === SeriesType.Standard ? value : d.d1);
|
2047 | const radius = 5;
|
2048 | const height = this.yScale.range()[0] - cy;
|
2049 | const opacity = 1;
|
2050 | let color;
|
2051 | if (this.colors.scaleType === ScaleType.Linear) {
|
2052 | if (this.type === SeriesType.Standard) {
|
2053 | color = this.colors.getColor(value);
|
2054 | }
|
2055 | else {
|
2056 | color = this.colors.getColor(d.d1);
|
2057 | }
|
2058 | }
|
2059 | else {
|
2060 | color = this.colors.getColor(seriesName);
|
2061 | }
|
2062 | const data = Object.assign({}, d, {
|
2063 | series: seriesName,
|
2064 | value,
|
2065 | name: label
|
2066 | });
|
2067 | return {
|
2068 | classNames: [`circle-data-${i}`],
|
2069 | value,
|
2070 | label,
|
2071 | data,
|
2072 | cx,
|
2073 | cy,
|
2074 | radius,
|
2075 | height,
|
2076 | tooltipLabel,
|
2077 | color,
|
2078 | opacity,
|
2079 | seriesName,
|
2080 | gradientStops: this.getGradientStops(color),
|
2081 | min: d.min,
|
2082 | max: d.max
|
2083 | };
|
2084 | }
|
2085 | getTooltipText({ tooltipLabel, value, seriesName, min, max }) {
|
2086 | return `
|
2087 | <span class="tooltip-label">${escapeLabel(seriesName)} • ${escapeLabel(tooltipLabel)}</span>
|
2088 | <span class="tooltip-val">${value.toLocaleString()}${this.getTooltipMinMaxText(min, max)}</span>
|
2089 | `;
|
2090 | }
|
2091 | getTooltipMinMaxText(min, max) {
|
2092 | if (min !== undefined || max !== undefined) {
|
2093 | let result = ' (';
|
2094 | if (min !== undefined) {
|
2095 | if (max === undefined) {
|
2096 | result += '≥';
|
2097 | }
|
2098 | result += min.toLocaleString();
|
2099 | if (max !== undefined) {
|
2100 | result += ' - ';
|
2101 | }
|
2102 | }
|
2103 | else if (max !== undefined) {
|
2104 | result += '≤';
|
2105 | }
|
2106 | if (max !== undefined) {
|
2107 | result += max.toLocaleString();
|
2108 | }
|
2109 | result += ')';
|
2110 | return result;
|
2111 | }
|
2112 | else {
|
2113 | return '';
|
2114 | }
|
2115 | }
|
2116 | getGradientStops(color) {
|
2117 | return [
|
2118 | {
|
2119 | offset: 0,
|
2120 | color,
|
2121 | opacity: 0.2
|
2122 | },
|
2123 | {
|
2124 | offset: 100,
|
2125 | color,
|
2126 | opacity: 1
|
2127 | }
|
2128 | ];
|
2129 | }
|
2130 | onClick(data) {
|
2131 | this.select.emit(data);
|
2132 | }
|
2133 | isActive(entry) {
|
2134 | if (!this.activeEntries)
|
2135 | return false;
|
2136 | const item = this.activeEntries.find(d => {
|
2137 | return entry.name === d.name;
|
2138 | });
|
2139 | return item !== undefined;
|
2140 | }
|
2141 | activateCircle() {
|
2142 | this.barVisible = true;
|
2143 | this.activate.emit({ name: this.data.name });
|
2144 | }
|
2145 | deactivateCircle() {
|
2146 | this.barVisible = false;
|
2147 | this.circle.opacity = 0;
|
2148 | this.deactivate.emit({ name: this.data.name });
|
2149 | }
|
2150 | }
|
2151 | CircleSeriesComponent.decorators = [
|
2152 | { type: Component, args: [{
|
2153 | selector: 'g[ngx-charts-circle-series]',
|
2154 | template: `
|
2155 | <svg:g *ngIf="circle">
|
2156 | <defs>
|
2157 | <svg:g
|
2158 | ngx-charts-svg-linear-gradient
|
2159 | [orientation]="barOrientation.Vertical"
|
2160 | [name]="gradientId"
|
2161 | [stops]="circle.gradientStops"
|
2162 | />
|
2163 | </defs>
|
2164 | <svg:rect
|
2165 | *ngIf="barVisible && type === 'standard'"
|
2166 | [@animationState]="'active'"
|
2167 | [attr.x]="circle.cx - circle.radius"
|
2168 | [attr.y]="circle.cy"
|
2169 | [attr.width]="circle.radius * 2"
|
2170 | [attr.height]="circle.height"
|
2171 | [attr.fill]="gradientFill"
|
2172 | class="tooltip-bar"
|
2173 | />
|
2174 | <svg:g
|
2175 | ngx-charts-circle
|
2176 | class="circle"
|
2177 | [cx]="circle.cx"
|
2178 | [cy]="circle.cy"
|
2179 | [r]="circle.radius"
|
2180 | [fill]="circle.color"
|
2181 | [class.active]="isActive({ name: circle.seriesName })"
|
2182 | [pointerEvents]="circle.value === 0 ? 'none' : 'all'"
|
2183 | [data]="circle.value"
|
2184 | [classNames]="circle.classNames"
|
2185 | (select)="onClick(circle.data)"
|
2186 | (activate)="activateCircle()"
|
2187 | (deactivate)="deactivateCircle()"
|
2188 | ngx-tooltip
|
2189 | [tooltipDisabled]="tooltipDisabled"
|
2190 | [tooltipPlacement]="placementTypes.Top"
|
2191 | [tooltipType]="styleTypes.tooltip"
|
2192 | [tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
2193 | [tooltipTemplate]="tooltipTemplate"
|
2194 | [tooltipContext]="circle.data"
|
2195 | />
|
2196 | </svg:g>
|
2197 | `,
|
2198 | changeDetection: ChangeDetectionStrategy.OnPush,
|
2199 | animations: [
|
2200 | trigger('animationState', [
|
2201 | transition(':enter', [
|
2202 | style({
|
2203 | opacity: 0
|
2204 | }),
|
2205 | animate(250, style({ opacity: 1 }))
|
2206 | ])
|
2207 | ])
|
2208 | ]
|
2209 | },] }
|
2210 | ];
|
2211 | CircleSeriesComponent.propDecorators = {
|
2212 | data: [{ type: Input }],
|
2213 | type: [{ type: Input }],
|
2214 | xScale: [{ type: Input }],
|
2215 | yScale: [{ type: Input }],
|
2216 | colors: [{ type: Input }],
|
2217 | scaleType: [{ type: Input }],
|
2218 | visibleValue: [{ type: Input }],
|
2219 | activeEntries: [{ type: Input }],
|
2220 | tooltipDisabled: [{ type: Input }],
|
2221 | tooltipTemplate: [{ type: Input }],
|
2222 | select: [{ type: Output }],
|
2223 | activate: [{ type: Output }],
|
2224 | deactivate: [{ type: Output }]
|
2225 | };
|
2226 |
|
2227 | class CircleComponent {
|
2228 | constructor() {
|
2229 | this.select = new EventEmitter();
|
2230 | this.activate = new EventEmitter();
|
2231 | this.deactivate = new EventEmitter();
|
2232 | }
|
2233 | onClick() {
|
2234 | this.select.emit(this.data);
|
2235 | }
|
2236 | onMouseEnter() {
|
2237 | this.activate.emit(this.data);
|
2238 | }
|
2239 | onMouseLeave() {
|
2240 | this.deactivate.emit(this.data);
|
2241 | }
|
2242 | ngOnChanges(changes) {
|
2243 | this.classNames = Array.isArray(this.classNames) ? this.classNames.join(' ') : '';
|
2244 | this.classNames += 'circle';
|
2245 | }
|
2246 | }
|
2247 | CircleComponent.decorators = [
|
2248 | { type: Component, args: [{
|
2249 | selector: 'g[ngx-charts-circle]',
|
2250 | template: `
|
2251 | <svg:circle
|
2252 | [attr.cx]="cx"
|
2253 | [attr.cy]="cy"
|
2254 | [attr.r]="r"
|
2255 | [attr.fill]="fill"
|
2256 | [attr.stroke]="stroke"
|
2257 | [attr.opacity]="circleOpacity"
|
2258 | [attr.class]="classNames"
|
2259 | [attr.pointer-events]="pointerEvents"
|
2260 | />
|
2261 | `,
|
2262 | changeDetection: ChangeDetectionStrategy.OnPush
|
2263 | },] }
|
2264 | ];
|
2265 | CircleComponent.propDecorators = {
|
2266 | cx: [{ type: Input }],
|
2267 | cy: [{ type: Input }],
|
2268 | r: [{ type: Input }],
|
2269 | fill: [{ type: Input }],
|
2270 | stroke: [{ type: Input }],
|
2271 | data: [{ type: Input }],
|
2272 | classNames: [{ type: Input }],
|
2273 | circleOpacity: [{ type: Input }],
|
2274 | pointerEvents: [{ type: Input }],
|
2275 | select: [{ type: Output }],
|
2276 | activate: [{ type: Output }],
|
2277 | deactivate: [{ type: Output }],
|
2278 | onClick: [{ type: HostListener, args: ['click',] }],
|
2279 | onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
2280 | onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
|
2281 | };
|
2282 |
|
2283 | class GridPanelComponent {
|
2284 | }
|
2285 | GridPanelComponent.decorators = [
|
2286 | { type: Component, args: [{
|
2287 | selector: 'g[ngx-charts-grid-panel]',
|
2288 | template: `
|
2289 | <svg:rect [attr.height]="height" [attr.width]="width" [attr.x]="x" [attr.y]="y" stroke="none" class="gridpanel" />
|
2290 | `,
|
2291 | changeDetection: ChangeDetectionStrategy.OnPush
|
2292 | },] }
|
2293 | ];
|
2294 | GridPanelComponent.propDecorators = {
|
2295 | width: [{ type: Input }],
|
2296 | height: [{ type: Input }],
|
2297 | x: [{ type: Input }],
|
2298 | y: [{ type: Input }]
|
2299 | };
|
2300 |
|
2301 | var ClassEnum;
|
2302 | (function (ClassEnum) {
|
2303 | ClassEnum["Odd"] = "odd";
|
2304 | ClassEnum["Even"] = "even";
|
2305 | })(ClassEnum || (ClassEnum = {}));
|
2306 | class GridPanelSeriesComponent {
|
2307 | ngOnChanges(changes) {
|
2308 | this.update();
|
2309 | }
|
2310 | update() {
|
2311 | this.gridPanels = this.getGridPanels();
|
2312 | }
|
2313 | getGridPanels() {
|
2314 | return this.data.map(d => {
|
2315 | let offset;
|
2316 | let width;
|
2317 | let height;
|
2318 | let x;
|
2319 | let y;
|
2320 | let className = ClassEnum.Odd;
|
2321 | if (this.orient === BarOrientation.Vertical) {
|
2322 | const position = this.xScale(d.name);
|
2323 | const positionIndex = Number.parseInt((position / this.xScale.step()).toString(), 10);
|
2324 | if (positionIndex % 2 === 1) {
|
2325 | className = ClassEnum.Even;
|
2326 | }
|
2327 | offset = this.xScale.bandwidth() * this.xScale.paddingInner();
|
2328 | width = this.xScale.bandwidth() + offset;
|
2329 | height = this.dims.height;
|
2330 | x = this.xScale(d.name) - offset / 2;
|
2331 | y = 0;
|
2332 | }
|
2333 | else if (this.orient === BarOrientation.Horizontal) {
|
2334 | const position = this.yScale(d.name);
|
2335 | const positionIndex = Number.parseInt((position / this.yScale.step()).toString(), 10);
|
2336 | if (positionIndex % 2 === 1) {
|
2337 | className = ClassEnum.Even;
|
2338 | }
|
2339 | offset = this.yScale.bandwidth() * this.yScale.paddingInner();
|
2340 | width = this.dims.width;
|
2341 | height = this.yScale.bandwidth() + offset;
|
2342 | x = 0;
|
2343 | y = this.yScale(d.name) - offset / 2;
|
2344 | }
|
2345 | return {
|
2346 | name: d.name,
|
2347 | class: className,
|
2348 | height,
|
2349 | width,
|
2350 | x,
|
2351 | y
|
2352 | };
|
2353 | });
|
2354 | }
|
2355 | }
|
2356 | GridPanelSeriesComponent.decorators = [
|
2357 | { type: Component, args: [{
|
2358 | selector: 'g[ngx-charts-grid-panel-series]',
|
2359 | template: `
|
2360 | <svg:g
|
2361 | ngx-charts-grid-panel
|
2362 | *ngFor="let gridPanel of gridPanels"
|
2363 | [height]="gridPanel.height"
|
2364 | [width]="gridPanel.width"
|
2365 | [x]="gridPanel.x"
|
2366 | [y]="gridPanel.y"
|
2367 | [class.grid-panel]="true"
|
2368 | [class.odd]="gridPanel.class === 'odd'"
|
2369 | [class.even]="gridPanel.class === 'even'"
|
2370 | ></svg:g>
|
2371 | `,
|
2372 | changeDetection: ChangeDetectionStrategy.OnPush
|
2373 | },] }
|
2374 | ];
|
2375 | GridPanelSeriesComponent.propDecorators = {
|
2376 | data: [{ type: Input }],
|
2377 | dims: [{ type: Input }],
|
2378 | xScale: [{ type: Input }],
|
2379 | yScale: [{ type: Input }],
|
2380 | orient: [{ type: Input }]
|
2381 | };
|
2382 |
|
2383 | class SvgLinearGradientComponent {
|
2384 | constructor() {
|
2385 | this.orientation = BarOrientation.Vertical;
|
2386 | }
|
2387 | ngOnChanges(changes) {
|
2388 | this.x1 = '0%';
|
2389 | this.x2 = '0%';
|
2390 | this.y1 = '0%';
|
2391 | this.y2 = '0%';
|
2392 | if (this.orientation === BarOrientation.Horizontal) {
|
2393 | this.x2 = '100%';
|
2394 | }
|
2395 | else if (this.orientation === BarOrientation.Vertical) {
|
2396 | this.y1 = '100%';
|
2397 | }
|
2398 | }
|
2399 | }
|
2400 | SvgLinearGradientComponent.decorators = [
|
2401 | { type: Component, args: [{
|
2402 | selector: 'g[ngx-charts-svg-linear-gradient]',
|
2403 | template: `
|
2404 | <svg:linearGradient [id]="name" [attr.x1]="x1" [attr.y1]="y1" [attr.x2]="x2" [attr.y2]="y2">
|
2405 | <svg:stop
|
2406 | *ngFor="let stop of stops"
|
2407 | [attr.offset]="stop.offset + '%'"
|
2408 | [style.stop-color]="stop.color"
|
2409 | [style.stop-opacity]="stop.opacity"
|
2410 | />
|
2411 | </svg:linearGradient>
|
2412 | `,
|
2413 | changeDetection: ChangeDetectionStrategy.OnPush
|
2414 | },] }
|
2415 | ];
|
2416 | SvgLinearGradientComponent.propDecorators = {
|
2417 | orientation: [{ type: Input }],
|
2418 | name: [{ type: Input }],
|
2419 | stops: [{ type: Input }]
|
2420 | };
|
2421 |
|
2422 | class SvgRadialGradientComponent {
|
2423 | constructor() {
|
2424 | this.endOpacity = 1;
|
2425 | this.cx = 0;
|
2426 | this.cy = 0;
|
2427 | }
|
2428 | get stops() {
|
2429 | return this.stopsInput || this.stopsDefault;
|
2430 | }
|
2431 | set stops(value) {
|
2432 | this.stopsInput = value;
|
2433 | }
|
2434 | ngOnChanges(changes) {
|
2435 | this.r = '30%';
|
2436 | if ('color' in changes || 'startOpacity' in changes || 'endOpacity' in changes) {
|
2437 | this.stopsDefault = [
|
2438 | {
|
2439 | offset: 0,
|
2440 | color: this.color,
|
2441 | opacity: this.startOpacity
|
2442 | },
|
2443 | {
|
2444 | offset: 100,
|
2445 | color: this.color,
|
2446 | opacity: this.endOpacity
|
2447 | }
|
2448 | ];
|
2449 | }
|
2450 | }
|
2451 | }
|
2452 | SvgRadialGradientComponent.decorators = [
|
2453 | { type: Component, args: [{
|
2454 | selector: 'g[ngx-charts-svg-radial-gradient]',
|
2455 | template: `
|
2456 | <svg:radialGradient [id]="name" [attr.cx]="cx" [attr.cy]="cy" [attr.r]="r" gradientUnits="userSpaceOnUse">
|
2457 | <svg:stop
|
2458 | *ngFor="let stop of stops"
|
2459 | [attr.offset]="stop.offset + '%'"
|
2460 | [style.stop-color]="stop.color"
|
2461 | [style.stop-opacity]="stop.opacity"
|
2462 | />
|
2463 | </svg:radialGradient>
|
2464 | `,
|
2465 | changeDetection: ChangeDetectionStrategy.OnPush
|
2466 | },] }
|
2467 | ];
|
2468 | SvgRadialGradientComponent.propDecorators = {
|
2469 | color: [{ type: Input }],
|
2470 | name: [{ type: Input }],
|
2471 | startOpacity: [{ type: Input }],
|
2472 | endOpacity: [{ type: Input }],
|
2473 | cx: [{ type: Input }],
|
2474 | cy: [{ type: Input }],
|
2475 | stops: [{ type: Input }]
|
2476 | };
|
2477 |
|
2478 | class AreaComponent {
|
2479 | constructor(element) {
|
2480 | this.opacity = 1;
|
2481 | this.startOpacity = 0.5;
|
2482 | this.endOpacity = 1;
|
2483 | this.gradient = false;
|
2484 | this.animations = true;
|
2485 | this.select = new EventEmitter();
|
2486 | this.animationsLoaded = false;
|
2487 | this.hasGradient = false;
|
2488 | this.barOrientation = BarOrientation;
|
2489 | this.element = element.nativeElement;
|
2490 | }
|
2491 | ngOnChanges() {
|
2492 | this.update();
|
2493 | if (!this.animationsLoaded) {
|
2494 | this.loadAnimation();
|
2495 | this.animationsLoaded = true;
|
2496 | }
|
2497 | }
|
2498 | update() {
|
2499 | this.gradientId = 'grad' + id().toString();
|
2500 | this.gradientFill = `url(#${this.gradientId})`;
|
2501 | if (this.gradient || this.stops) {
|
2502 | this.gradientStops = this.getGradient();
|
2503 | this.hasGradient = true;
|
2504 | }
|
2505 | else {
|
2506 | this.hasGradient = false;
|
2507 | }
|
2508 | this.updatePathEl();
|
2509 | }
|
2510 | loadAnimation() {
|
2511 | this.areaPath = this.startingPath;
|
2512 | setTimeout(this.updatePathEl.bind(this), 100);
|
2513 | }
|
2514 | updatePathEl() {
|
2515 | const node = select(this.element).select('.area');
|
2516 | if (this.animations) {
|
2517 | node.transition().duration(750).attr('d', this.path);
|
2518 | }
|
2519 | else {
|
2520 | node.attr('d', this.path);
|
2521 | }
|
2522 | }
|
2523 | getGradient() {
|
2524 | if (this.stops) {
|
2525 | return this.stops;
|
2526 | }
|
2527 | return [
|
2528 | {
|
2529 | offset: 0,
|
2530 | color: this.fill,
|
2531 | opacity: this.startOpacity
|
2532 | },
|
2533 | {
|
2534 | offset: 100,
|
2535 | color: this.fill,
|
2536 | opacity: this.endOpacity
|
2537 | }
|
2538 | ];
|
2539 | }
|
2540 | }
|
2541 | AreaComponent.decorators = [
|
2542 | { type: Component, args: [{
|
2543 | selector: 'g[ngx-charts-area]',
|
2544 | template: `
|
2545 | <svg:defs *ngIf="gradient">
|
2546 | <svg:g
|
2547 | ngx-charts-svg-linear-gradient
|
2548 | [orientation]="barOrientation.Vertical"
|
2549 | [name]="gradientId"
|
2550 | [stops]="gradientStops"
|
2551 | />
|
2552 | </svg:defs>
|
2553 | <svg:path class="area" [attr.d]="areaPath" [attr.fill]="gradient ? gradientFill : fill" [style.opacity]="opacity" />
|
2554 | `,
|
2555 | changeDetection: ChangeDetectionStrategy.OnPush
|
2556 | },] }
|
2557 | ];
|
2558 | AreaComponent.ctorParameters = () => [
|
2559 | { type: ElementRef }
|
2560 | ];
|
2561 | AreaComponent.propDecorators = {
|
2562 | data: [{ type: Input }],
|
2563 | path: [{ type: Input }],
|
2564 | startingPath: [{ type: Input }],
|
2565 | fill: [{ type: Input }],
|
2566 | opacity: [{ type: Input }],
|
2567 | startOpacity: [{ type: Input }],
|
2568 | endOpacity: [{ type: Input }],
|
2569 | gradient: [{ type: Input }],
|
2570 | stops: [{ type: Input }],
|
2571 | animations: [{ type: Input }],
|
2572 | select: [{ type: Output }]
|
2573 | };
|
2574 |
|
2575 |
|
2576 | function easeOutExpo(t, b, c, d) {
|
2577 | return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
|
2578 | }
|
2579 |
|
2580 |
|
2581 |
|
2582 | function count(countFrom, countTo, countDecimals, countDuration, callback) {
|
2583 | const startVal = Number(countFrom);
|
2584 | const endVal = Number(countTo);
|
2585 | const countDown = startVal > endVal;
|
2586 | const decimals = Math.max(0, countDecimals);
|
2587 | const dec = Math.pow(10, decimals);
|
2588 | const duration = Number(countDuration) * 1000;
|
2589 | let startTime;
|
2590 | function runCount(timestamp) {
|
2591 | let frameVal;
|
2592 | const progress = timestamp - startTime;
|
2593 | if (countDown) {
|
2594 | frameVal = startVal - easeOutExpo(progress, 0, startVal - endVal, duration);
|
2595 | }
|
2596 | else {
|
2597 | frameVal = easeOutExpo(progress, startVal, endVal - startVal, duration);
|
2598 | }
|
2599 | if (countDown) {
|
2600 | frameVal = frameVal < endVal ? endVal : frameVal;
|
2601 | }
|
2602 | else {
|
2603 | frameVal = frameVal > endVal ? endVal : frameVal;
|
2604 | }
|
2605 | frameVal = Math.round(frameVal * dec) / dec;
|
2606 | const tick = progress < duration;
|
2607 | callback({
|
2608 | value: frameVal,
|
2609 | progress,
|
2610 | timestamp,
|
2611 | finished: !tick
|
2612 | });
|
2613 | if (tick) {
|
2614 | return requestAnimationFrame(val => runCount(val));
|
2615 | }
|
2616 | }
|
2617 | return requestAnimationFrame(timestamp => {
|
2618 | startTime = timestamp;
|
2619 | return runCount(timestamp);
|
2620 | });
|
2621 | }
|
2622 |
|
2623 |
|
2624 |
|
2625 |
|
2626 |
|
2627 | function decimalChecker(countTo) {
|
2628 | const endVal = Number(countTo);
|
2629 | if (endVal % 1 !== 0 && Math.abs(endVal) <= 10) {
|
2630 | return 2;
|
2631 | }
|
2632 | return 0;
|
2633 | }
|
2634 |
|
2635 |
|
2636 |
|
2637 |
|
2638 |
|
2639 |
|
2640 |
|
2641 |
|
2642 |
|
2643 |
|
2644 | class CountUpDirective {
|
2645 | constructor(cd, element) {
|
2646 | this.cd = cd;
|
2647 | this.countDuration = 1;
|
2648 | this.countPrefix = '';
|
2649 | this.countSuffix = '';
|
2650 | this.countChange = new EventEmitter();
|
2651 | this.countFinish = new EventEmitter();
|
2652 | this.value = '';
|
2653 | this._countDecimals = 0;
|
2654 | this._countTo = 0;
|
2655 | this._countFrom = 0;
|
2656 | this.nativeElement = element.nativeElement;
|
2657 | }
|
2658 | set countDecimals(val) {
|
2659 | this._countDecimals = val;
|
2660 | }
|
2661 | get countDecimals() {
|
2662 | if (this._countDecimals)
|
2663 | return this._countDecimals;
|
2664 | return decimalChecker(this.countTo);
|
2665 | }
|
2666 | set countTo(val) {
|
2667 | this._countTo = parseFloat(val);
|
2668 | this.start();
|
2669 | }
|
2670 | get countTo() {
|
2671 | return this._countTo;
|
2672 | }
|
2673 | set countFrom(val) {
|
2674 | this._countFrom = parseFloat(val);
|
2675 | this.start();
|
2676 | }
|
2677 | get countFrom() {
|
2678 | return this._countFrom;
|
2679 | }
|
2680 | ngOnDestroy() {
|
2681 | cancelAnimationFrame(this.animationReq);
|
2682 | }
|
2683 | start() {
|
2684 | cancelAnimationFrame(this.animationReq);
|
2685 | const valueFormatting = this.valueFormatting || (value => `${this.countPrefix}${value.toLocaleString()}${this.countSuffix}`);
|
2686 | const callback = ({ value, progress, finished }) => {
|
2687 | this.value = valueFormatting(value);
|
2688 | this.cd.markForCheck();
|
2689 | if (!finished)
|
2690 | this.countChange.emit({ value: this.value, progress });
|
2691 | if (finished)
|
2692 | this.countFinish.emit({ value: this.value, progress });
|
2693 | };
|
2694 | this.animationReq = count(this.countFrom, this.countTo, this.countDecimals, this.countDuration, callback);
|
2695 | }
|
2696 | }
|
2697 | CountUpDirective.decorators = [
|
2698 | { type: Component, args: [{
|
2699 | selector: '[ngx-charts-count-up]',
|
2700 | template: ` {{ value }} `
|
2701 | },] }
|
2702 | ];
|
2703 | CountUpDirective.ctorParameters = () => [
|
2704 | { type: ChangeDetectorRef },
|
2705 | { type: ElementRef }
|
2706 | ];
|
2707 | CountUpDirective.propDecorators = {
|
2708 | countDuration: [{ type: Input }],
|
2709 | countPrefix: [{ type: Input }],
|
2710 | countSuffix: [{ type: Input }],
|
2711 | valueFormatting: [{ type: Input }],
|
2712 | countDecimals: [{ type: Input }],
|
2713 | countTo: [{ type: Input }],
|
2714 | countFrom: [{ type: Input }],
|
2715 | countChange: [{ type: Output }],
|
2716 | countFinish: [{ type: Output }]
|
2717 | };
|
2718 |
|
2719 |
|
2720 |
|
2721 | let root;
|
2722 | if (typeof window !== 'undefined') {
|
2723 | root = window;
|
2724 | }
|
2725 | else if (typeof global !== 'undefined') {
|
2726 | root = global;
|
2727 | }
|
2728 |
|
2729 | const MouseEvent = root.MouseEvent;
|
2730 | function createMouseEvent(name, bubbles = false, cancelable = true) {
|
2731 |
|
2732 |
|
2733 | if (typeof MouseEvent === 'function') {
|
2734 |
|
2735 | return new MouseEvent(name, { bubbles, cancelable });
|
2736 | }
|
2737 | else {
|
2738 |
|
2739 | const event = document.createEvent('MouseEvent');
|
2740 | event.initEvent(name, bubbles, cancelable);
|
2741 | return event;
|
2742 | }
|
2743 | }
|
2744 |
|
2745 | class TooltipArea {
|
2746 | constructor(platformId) {
|
2747 | this.platformId = platformId;
|
2748 | this.anchorOpacity = 0;
|
2749 | this.anchorPos = -1;
|
2750 | this.anchorValues = [];
|
2751 | this.placementTypes = PlacementTypes;
|
2752 | this.styleTypes = StyleTypes;
|
2753 | this.showPercentage = false;
|
2754 | this.tooltipDisabled = false;
|
2755 | this.hover = new EventEmitter();
|
2756 | }
|
2757 | getValues(xVal) {
|
2758 | const results = [];
|
2759 | for (const group of this.results) {
|
2760 | const item = group.series.find(d => d.name.toString() === xVal.toString());
|
2761 | let groupName = group.name;
|
2762 | if (groupName instanceof Date) {
|
2763 | groupName = groupName.toLocaleDateString();
|
2764 | }
|
2765 | if (item) {
|
2766 | const label = item.name;
|
2767 | let val = item.value;
|
2768 | if (this.showPercentage) {
|
2769 | val = (item.d1 - item.d0).toFixed(2) + '%';
|
2770 | }
|
2771 | let color;
|
2772 | if (this.colors.scaleType === ScaleType.Linear) {
|
2773 | let v = val;
|
2774 | if (item.d1) {
|
2775 | v = item.d1;
|
2776 | }
|
2777 | color = this.colors.getColor(v);
|
2778 | }
|
2779 | else {
|
2780 | color = this.colors.getColor(group.name);
|
2781 | }
|
2782 | const data = Object.assign({}, item, {
|
2783 | value: val,
|
2784 | name: label,
|
2785 | series: groupName,
|
2786 | min: item.min,
|
2787 | max: item.max,
|
2788 | color
|
2789 | });
|
2790 | results.push(data);
|
2791 | }
|
2792 | }
|
2793 | return results;
|
2794 | }
|
2795 | mouseMove(event) {
|
2796 | if (!isPlatformBrowser(this.platformId)) {
|
2797 | return;
|
2798 | }
|
2799 | const xPos = event.pageX - event.target.getBoundingClientRect().left;
|
2800 | const closestIndex = this.findClosestPointIndex(xPos);
|
2801 | const closestPoint = this.xSet[closestIndex];
|
2802 | this.anchorPos = this.xScale(closestPoint);
|
2803 | this.anchorPos = Math.max(0, this.anchorPos);
|
2804 | this.anchorPos = Math.min(this.dims.width, this.anchorPos);
|
2805 | this.anchorValues = this.getValues(closestPoint);
|
2806 | if (this.anchorPos !== this.lastAnchorPos) {
|
2807 | const ev = createMouseEvent('mouseleave');
|
2808 | this.tooltipAnchor.nativeElement.dispatchEvent(ev);
|
2809 | this.anchorOpacity = 0.7;
|
2810 | this.hover.emit({
|
2811 | value: closestPoint
|
2812 | });
|
2813 | this.showTooltip();
|
2814 | this.lastAnchorPos = this.anchorPos;
|
2815 | }
|
2816 | }
|
2817 | findClosestPointIndex(xPos) {
|
2818 | let minIndex = 0;
|
2819 | let maxIndex = this.xSet.length - 1;
|
2820 | let minDiff = Number.MAX_VALUE;
|
2821 | let closestIndex = 0;
|
2822 | while (minIndex <= maxIndex) {
|
2823 | const currentIndex = ((minIndex + maxIndex) / 2) | 0;
|
2824 | const currentElement = this.xScale(this.xSet[currentIndex]);
|
2825 | const curDiff = Math.abs(currentElement - xPos);
|
2826 | if (curDiff < minDiff) {
|
2827 | minDiff = curDiff;
|
2828 | closestIndex = currentIndex;
|
2829 | }
|
2830 | if (currentElement < xPos) {
|
2831 | minIndex = currentIndex + 1;
|
2832 | }
|
2833 | else if (currentElement > xPos) {
|
2834 | maxIndex = currentIndex - 1;
|
2835 | }
|
2836 | else {
|
2837 | minDiff = 0;
|
2838 | closestIndex = currentIndex;
|
2839 | break;
|
2840 | }
|
2841 | }
|
2842 | return closestIndex;
|
2843 | }
|
2844 | showTooltip() {
|
2845 | const event = createMouseEvent('mouseenter');
|
2846 | this.tooltipAnchor.nativeElement.dispatchEvent(event);
|
2847 | }
|
2848 | hideTooltip() {
|
2849 | const event = createMouseEvent('mouseleave');
|
2850 | this.tooltipAnchor.nativeElement.dispatchEvent(event);
|
2851 | this.anchorOpacity = 0;
|
2852 | this.lastAnchorPos = -1;
|
2853 | }
|
2854 | getToolTipText(tooltipItem) {
|
2855 | let result = '';
|
2856 | if (tooltipItem.series !== undefined) {
|
2857 | result += tooltipItem.series;
|
2858 | }
|
2859 | else {
|
2860 | result += '???';
|
2861 | }
|
2862 | result += ': ';
|
2863 | if (tooltipItem.value !== undefined) {
|
2864 | result += tooltipItem.value.toLocaleString();
|
2865 | }
|
2866 | if (tooltipItem.min !== undefined || tooltipItem.max !== undefined) {
|
2867 | result += ' (';
|
2868 | if (tooltipItem.min !== undefined) {
|
2869 | if (tooltipItem.max === undefined) {
|
2870 | result += '≥';
|
2871 | }
|
2872 | result += tooltipItem.min.toLocaleString();
|
2873 | if (tooltipItem.max !== undefined) {
|
2874 | result += ' - ';
|
2875 | }
|
2876 | }
|
2877 | else if (tooltipItem.max !== undefined) {
|
2878 | result += '≤';
|
2879 | }
|
2880 | if (tooltipItem.max !== undefined) {
|
2881 | result += tooltipItem.max.toLocaleString();
|
2882 | }
|
2883 | result += ')';
|
2884 | }
|
2885 | return result;
|
2886 | }
|
2887 | }
|
2888 | TooltipArea.decorators = [
|
2889 | { type: Component, args: [{
|
2890 | selector: 'g[ngx-charts-tooltip-area]',
|
2891 | template: `
|
2892 | <svg:g>
|
2893 | <svg:rect
|
2894 | class="tooltip-area"
|
2895 | [attr.x]="0"
|
2896 | y="0"
|
2897 | [attr.width]="dims.width"
|
2898 | [attr.height]="dims.height"
|
2899 | style="opacity: 0; cursor: 'auto';"
|
2900 | (mousemove)="mouseMove($event)"
|
2901 | (mouseleave)="hideTooltip()"
|
2902 | />
|
2903 | <ng-template #defaultTooltipTemplate let-model="model">
|
2904 | <xhtml:div class="area-tooltip-container">
|
2905 | <xhtml:div *ngFor="let tooltipItem of model" class="tooltip-item">
|
2906 | <xhtml:span class="tooltip-item-color" [style.background-color]="tooltipItem.color"></xhtml:span>
|
2907 | {{ getToolTipText(tooltipItem) }}
|
2908 | </xhtml:div>
|
2909 | </xhtml:div>
|
2910 | </ng-template>
|
2911 | <svg:rect
|
2912 | #tooltipAnchor
|
2913 | [@animationState]="anchorOpacity !== 0 ? 'active' : 'inactive'"
|
2914 | class="tooltip-anchor"
|
2915 | [attr.x]="anchorPos"
|
2916 | y="0"
|
2917 | [attr.width]="1"
|
2918 | [attr.height]="dims.height"
|
2919 | [style.opacity]="anchorOpacity"
|
2920 | [style.pointer-events]="'none'"
|
2921 | ngx-tooltip
|
2922 | [tooltipDisabled]="tooltipDisabled"
|
2923 | [tooltipPlacement]="placementTypes.Right"
|
2924 | [tooltipType]="styleTypes.tooltip"
|
2925 | [tooltipSpacing]="15"
|
2926 | [tooltipTemplate]="tooltipTemplate ? tooltipTemplate : defaultTooltipTemplate"
|
2927 | [tooltipContext]="anchorValues"
|
2928 | [tooltipImmediateExit]="true"
|
2929 | />
|
2930 | </svg:g>
|
2931 | `,
|
2932 | changeDetection: ChangeDetectionStrategy.OnPush,
|
2933 | animations: [
|
2934 | trigger('animationState', [
|
2935 | transition('inactive => active', [
|
2936 | style({
|
2937 | opacity: 0
|
2938 | }),
|
2939 | animate(250, style({ opacity: 0.7 }))
|
2940 | ]),
|
2941 | transition('active => inactive', [
|
2942 | style({
|
2943 | opacity: 0.7
|
2944 | }),
|
2945 | animate(250, style({ opacity: 0 }))
|
2946 | ])
|
2947 | ])
|
2948 | ]
|
2949 | },] }
|
2950 | ];
|
2951 | TooltipArea.ctorParameters = () => [
|
2952 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
2953 | ];
|
2954 | TooltipArea.propDecorators = {
|
2955 | dims: [{ type: Input }],
|
2956 | xSet: [{ type: Input }],
|
2957 | xScale: [{ type: Input }],
|
2958 | yScale: [{ type: Input }],
|
2959 | results: [{ type: Input }],
|
2960 | colors: [{ type: Input }],
|
2961 | showPercentage: [{ type: Input }],
|
2962 | tooltipDisabled: [{ type: Input }],
|
2963 | tooltipTemplate: [{ type: Input }],
|
2964 | hover: [{ type: Output }],
|
2965 | tooltipAnchor: [{ type: ViewChild, args: ['tooltipAnchor', { static: false },] }]
|
2966 | };
|
2967 |
|
2968 | class Timeline {
|
2969 | constructor(element, cd) {
|
2970 | this.cd = cd;
|
2971 | this.height = 50;
|
2972 | this.select = new EventEmitter();
|
2973 | this.onDomainChange = new EventEmitter();
|
2974 | this.initialized = false;
|
2975 | this.element = element.nativeElement;
|
2976 | }
|
2977 | ngOnChanges(changes) {
|
2978 | this.update();
|
2979 | if (!this.initialized) {
|
2980 | this.addBrush();
|
2981 | this.initialized = true;
|
2982 | }
|
2983 | }
|
2984 | update() {
|
2985 | this.dims = this.getDims();
|
2986 | this.height = this.dims.height;
|
2987 | const offsetY = this.view[1] - this.height;
|
2988 | this.xDomain = this.getXDomain();
|
2989 | this.xScale = this.getXScale();
|
2990 | if (this.brush) {
|
2991 | this.updateBrush();
|
2992 | }
|
2993 | this.transform = `translate(0 , ${offsetY})`;
|
2994 | this.filterId = 'filter' + id().toString();
|
2995 | this.filter = `url(#${this.filterId})`;
|
2996 | this.cd.markForCheck();
|
2997 | }
|
2998 | getXDomain() {
|
2999 | let values = [];
|
3000 | for (const results of this.results) {
|
3001 | for (const d of results.series) {
|
3002 | if (!values.includes(d.name)) {
|
3003 | values.push(d.name);
|
3004 | }
|
3005 | }
|
3006 | }
|
3007 | let domain = [];
|
3008 | if (this.scaleType === ScaleType.Time) {
|
3009 | const min = Math.min(...values);
|
3010 | const max = Math.max(...values);
|
3011 | domain = [min, max];
|
3012 | }
|
3013 | else if (this.scaleType === ScaleType.Linear) {
|
3014 | values = values.map(v => Number(v));
|
3015 | const min = Math.min(...values);
|
3016 | const max = Math.max(...values);
|
3017 | domain = [min, max];
|
3018 | }
|
3019 | else {
|
3020 | domain = values;
|
3021 | }
|
3022 | return domain;
|
3023 | }
|
3024 | getXScale() {
|
3025 | let scale;
|
3026 | if (this.scaleType === ScaleType.Time) {
|
3027 | scale = scaleTime().range([0, this.dims.width]).domain(this.xDomain);
|
3028 | }
|
3029 | else if (this.scaleType === ScaleType.Linear) {
|
3030 | scale = scaleLinear().range([0, this.dims.width]).domain(this.xDomain);
|
3031 | }
|
3032 | else if (this.scaleType === ScaleType.Ordinal) {
|
3033 | scale = scalePoint().range([0, this.dims.width]).padding(0.1).domain(this.xDomain);
|
3034 | }
|
3035 | return scale;
|
3036 | }
|
3037 | addBrush() {
|
3038 | if (this.brush)
|
3039 | return;
|
3040 | const height = this.height;
|
3041 | const width = this.view[0];
|
3042 | this.brush = brushX()
|
3043 | .extent([
|
3044 | [0, 0],
|
3045 | [width, height]
|
3046 | ])
|
3047 | .on('brush end', ({ selection }) => {
|
3048 | const newSelection = selection || this.xScale.range();
|
3049 | const newDomain = newSelection.map(this.xScale.invert);
|
3050 | this.onDomainChange.emit(newDomain);
|
3051 | this.cd.markForCheck();
|
3052 | });
|
3053 | select(this.element).select('.brush').call(this.brush);
|
3054 | }
|
3055 | updateBrush() {
|
3056 | if (!this.brush)
|
3057 | return;
|
3058 | const height = this.height;
|
3059 | const width = this.view[0];
|
3060 | this.brush.extent([
|
3061 | [0, 0],
|
3062 | [width, height]
|
3063 | ]);
|
3064 | select(this.element).select('.brush').call(this.brush);
|
3065 |
|
3066 | select(this.element)
|
3067 | .select('.selection')
|
3068 | .attr('fill', undefined)
|
3069 | .attr('stroke', undefined)
|
3070 | .attr('fill-opacity', undefined);
|
3071 | this.cd.markForCheck();
|
3072 | }
|
3073 | getDims() {
|
3074 | const width = this.view[0];
|
3075 | const dims = {
|
3076 | width,
|
3077 | height: this.height
|
3078 | };
|
3079 | return dims;
|
3080 | }
|
3081 | }
|
3082 | Timeline.decorators = [
|
3083 | { type: Component, args: [{
|
3084 | selector: 'g[ngx-charts-timeline]',
|
3085 | template: `
|
3086 | <svg:g class="timeline" [attr.transform]="transform">
|
3087 | <svg:filter [attr.id]="filterId">
|
3088 | <svg:feColorMatrix
|
3089 | in="SourceGraphic"
|
3090 | type="matrix"
|
3091 | 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"
|
3092 | />
|
3093 | </svg:filter>
|
3094 | <svg:g class="embedded-chart">
|
3095 | <ng-content></ng-content>
|
3096 | </svg:g>
|
3097 | <svg:rect x="0" [attr.width]="view[0]" y="0" [attr.height]="height" class="brush-background" />
|
3098 | <svg:g class="brush"></svg:g>
|
3099 | </svg:g>
|
3100 | `,
|
3101 | encapsulation: ViewEncapsulation.None,
|
3102 | changeDetection: ChangeDetectionStrategy.OnPush,
|
3103 | 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"]
|
3104 | },] }
|
3105 | ];
|
3106 | Timeline.ctorParameters = () => [
|
3107 | { type: ElementRef },
|
3108 | { type: ChangeDetectorRef }
|
3109 | ];
|
3110 | Timeline.propDecorators = {
|
3111 | view: [{ type: Input }],
|
3112 | results: [{ type: Input }],
|
3113 | scheme: [{ type: Input }],
|
3114 | customColors: [{ type: Input }],
|
3115 | legend: [{ type: Input }],
|
3116 | autoScale: [{ type: Input }],
|
3117 | scaleType: [{ type: Input }],
|
3118 | height: [{ type: Input }],
|
3119 | select: [{ type: Output }],
|
3120 | onDomainChange: [{ type: Output }]
|
3121 | };
|
3122 |
|
3123 | class LegendComponent {
|
3124 | constructor(cd) {
|
3125 | this.cd = cd;
|
3126 | this.horizontal = false;
|
3127 | this.labelClick = new EventEmitter();
|
3128 | this.labelActivate = new EventEmitter();
|
3129 | this.labelDeactivate = new EventEmitter();
|
3130 | this.legendEntries = [];
|
3131 | }
|
3132 | ngOnChanges(changes) {
|
3133 | this.update();
|
3134 | }
|
3135 | update() {
|
3136 | this.cd.markForCheck();
|
3137 | this.legendEntries = this.getLegendEntries();
|
3138 | }
|
3139 | getLegendEntries() {
|
3140 | const items = [];
|
3141 | for (const label of this.data) {
|
3142 | const formattedLabel = formatLabel(label);
|
3143 | const idx = items.findIndex(i => {
|
3144 | return i.label === formattedLabel;
|
3145 | });
|
3146 | if (idx === -1) {
|
3147 | items.push({
|
3148 | label,
|
3149 | formattedLabel,
|
3150 | color: this.colors.getColor(label)
|
3151 | });
|
3152 | }
|
3153 | }
|
3154 | return items;
|
3155 | }
|
3156 | isActive(entry) {
|
3157 | if (!this.activeEntries)
|
3158 | return false;
|
3159 | const item = this.activeEntries.find(d => {
|
3160 | return entry.label === d.name;
|
3161 | });
|
3162 | return item !== undefined;
|
3163 | }
|
3164 | activate(item) {
|
3165 | this.labelActivate.emit(item);
|
3166 | }
|
3167 | deactivate(item) {
|
3168 | this.labelDeactivate.emit(item);
|
3169 | }
|
3170 | trackBy(index, item) {
|
3171 | return item.label;
|
3172 | }
|
3173 | }
|
3174 | LegendComponent.decorators = [
|
3175 | { type: Component, args: [{
|
3176 | selector: 'ngx-charts-legend',
|
3177 | template: `
|
3178 | <div [style.width.px]="width">
|
3179 | <header class="legend-title" *ngIf="title?.length > 0">
|
3180 | <span class="legend-title-text">{{ title }}</span>
|
3181 | </header>
|
3182 | <div class="legend-wrap">
|
3183 | <ul class="legend-labels" [class.horizontal-legend]="horizontal" [style.max-height.px]="height - 45">
|
3184 | <li *ngFor="let entry of legendEntries; trackBy: trackBy" class="legend-label">
|
3185 | <ngx-charts-legend-entry
|
3186 | [label]="entry.label"
|
3187 | [formattedLabel]="entry.formattedLabel"
|
3188 | [color]="entry.color"
|
3189 | [isActive]="isActive(entry)"
|
3190 | (select)="labelClick.emit($event)"
|
3191 | (activate)="activate($event)"
|
3192 | (deactivate)="deactivate($event)"
|
3193 | >
|
3194 | </ngx-charts-legend-entry>
|
3195 | </li>
|
3196 | </ul>
|
3197 | </div>
|
3198 | </div>
|
3199 | `,
|
3200 | encapsulation: ViewEncapsulation.None,
|
3201 | changeDetection: ChangeDetectionStrategy.OnPush,
|
3202 | 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:bold}.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"]
|
3203 | },] }
|
3204 | ];
|
3205 | LegendComponent.ctorParameters = () => [
|
3206 | { type: ChangeDetectorRef }
|
3207 | ];
|
3208 | LegendComponent.propDecorators = {
|
3209 | data: [{ type: Input }],
|
3210 | title: [{ type: Input }],
|
3211 | colors: [{ type: Input }],
|
3212 | height: [{ type: Input }],
|
3213 | width: [{ type: Input }],
|
3214 | activeEntries: [{ type: Input }],
|
3215 | horizontal: [{ type: Input }],
|
3216 | labelClick: [{ type: Output }],
|
3217 | labelActivate: [{ type: Output }],
|
3218 | labelDeactivate: [{ type: Output }]
|
3219 | };
|
3220 |
|
3221 | class LegendEntryComponent {
|
3222 | constructor() {
|
3223 | this.isActive = false;
|
3224 | this.select = new EventEmitter();
|
3225 | this.activate = new EventEmitter();
|
3226 | this.deactivate = new EventEmitter();
|
3227 | this.toggle = new EventEmitter();
|
3228 | }
|
3229 | get trimmedLabel() {
|
3230 | return this.formattedLabel || '(empty)';
|
3231 | }
|
3232 | onMouseEnter() {
|
3233 | this.activate.emit({ name: this.label });
|
3234 | }
|
3235 | onMouseLeave() {
|
3236 | this.deactivate.emit({ name: this.label });
|
3237 | }
|
3238 | }
|
3239 | LegendEntryComponent.decorators = [
|
3240 | { type: Component, args: [{
|
3241 | selector: 'ngx-charts-legend-entry',
|
3242 | template: `
|
3243 | <span [title]="formattedLabel" tabindex="-1" [class.active]="isActive" (click)="select.emit(formattedLabel)">
|
3244 | <span class="legend-label-color" [style.background-color]="color" (click)="toggle.emit(formattedLabel)"> </span>
|
3245 | <span class="legend-label-text">
|
3246 | {{ trimmedLabel }}
|
3247 | </span>
|
3248 | </span>
|
3249 | `,
|
3250 | changeDetection: ChangeDetectionStrategy.OnPush
|
3251 | },] }
|
3252 | ];
|
3253 | LegendEntryComponent.propDecorators = {
|
3254 | color: [{ type: Input }],
|
3255 | label: [{ type: Input }],
|
3256 | formattedLabel: [{ type: Input }],
|
3257 | isActive: [{ type: Input }],
|
3258 | select: [{ type: Output }],
|
3259 | activate: [{ type: Output }],
|
3260 | deactivate: [{ type: Output }],
|
3261 | toggle: [{ type: Output }],
|
3262 | onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
3263 | onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
|
3264 | };
|
3265 |
|
3266 | class ScaleLegendComponent {
|
3267 | constructor() {
|
3268 | this.horizontal = false;
|
3269 | }
|
3270 | ngOnChanges(changes) {
|
3271 | const gradientValues = this.gradientString(this.colors.range(), this.colors.domain());
|
3272 | const direction = this.horizontal ? 'right' : 'bottom';
|
3273 | this.gradient = `linear-gradient(to ${direction}, ${gradientValues})`;
|
3274 | }
|
3275 | |
3276 |
|
3277 |
|
3278 |
|
3279 |
|
3280 | gradientString(colors, splits) {
|
3281 |
|
3282 | splits.push(1);
|
3283 | const pairs = [];
|
3284 | colors.reverse().forEach((c, i) => {
|
3285 | pairs.push(`${c} ${Math.round(splits[i] * 100)}%`);
|
3286 | });
|
3287 | return pairs.join(', ');
|
3288 | }
|
3289 | }
|
3290 | ScaleLegendComponent.decorators = [
|
3291 | { type: Component, args: [{
|
3292 | selector: 'ngx-charts-scale-legend',
|
3293 | template: `
|
3294 | <div
|
3295 | class="scale-legend"
|
3296 | [class.horizontal-legend]="horizontal"
|
3297 | [style.height.px]="horizontal ? undefined : height"
|
3298 | [style.width.px]="width"
|
3299 | >
|
3300 | <div class="scale-legend-label">
|
3301 | <span>{{ valueRange[1].toLocaleString() }}</span>
|
3302 | </div>
|
3303 | <div class="scale-legend-wrap" [style.background]="gradient"></div>
|
3304 | <div class="scale-legend-label">
|
3305 | <span>{{ valueRange[0].toLocaleString() }}</span>
|
3306 | </div>
|
3307 | </div>
|
3308 | `,
|
3309 | encapsulation: ViewEncapsulation.None,
|
3310 | changeDetection: ChangeDetectionStrategy.OnPush,
|
3311 | 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"]
|
3312 | },] }
|
3313 | ];
|
3314 | ScaleLegendComponent.propDecorators = {
|
3315 | valueRange: [{ type: Input }],
|
3316 | colors: [{ type: Input }],
|
3317 | height: [{ type: Input }],
|
3318 | width: [{ type: Input }],
|
3319 | horizontal: [{ type: Input }]
|
3320 | };
|
3321 |
|
3322 | class AdvancedLegendComponent {
|
3323 | constructor() {
|
3324 | this.label = 'Total';
|
3325 | this.animations = true;
|
3326 | this.select = new EventEmitter();
|
3327 | this.activate = new EventEmitter();
|
3328 | this.deactivate = new EventEmitter();
|
3329 | this.legendItems = [];
|
3330 | this.labelFormatting = label => label;
|
3331 | this.percentageFormatting = percentage => percentage;
|
3332 | this.defaultValueFormatting = value => value.toLocaleString();
|
3333 | }
|
3334 | ngOnChanges(changes) {
|
3335 | this.update();
|
3336 | }
|
3337 | getTotal() {
|
3338 | return this.data.map(d => Number(d.value)).reduce((sum, d) => sum + d, 0);
|
3339 | }
|
3340 | update() {
|
3341 | this.total = this.getTotal();
|
3342 | this.roundedTotal = this.total;
|
3343 | this.legendItems = this.getLegendItems();
|
3344 | }
|
3345 | getLegendItems() {
|
3346 | return this.data.map(d => {
|
3347 | const label = formatLabel(d.name);
|
3348 | const value = d.value;
|
3349 | const color = this.colors.getColor(label);
|
3350 | const percentage = this.total > 0 ? (value / this.total) * 100 : 0;
|
3351 | const formattedLabel = typeof this.labelFormatting === 'function' ? this.labelFormatting(label) : label;
|
3352 | return {
|
3353 | _value: value,
|
3354 | data: d,
|
3355 | value,
|
3356 | color,
|
3357 | label: formattedLabel,
|
3358 | displayLabel: trimLabel(formattedLabel, 20),
|
3359 | origialLabel: d.name,
|
3360 | percentage: this.percentageFormatting ? this.percentageFormatting(percentage) : percentage.toLocaleString()
|
3361 | };
|
3362 | });
|
3363 | }
|
3364 | trackBy(index, item) {
|
3365 | return item.label;
|
3366 | }
|
3367 | }
|
3368 | AdvancedLegendComponent.decorators = [
|
3369 | { type: Component, args: [{
|
3370 | selector: 'ngx-charts-advanced-legend',
|
3371 | template: `
|
3372 | <div class="advanced-pie-legend" [style.width.px]="width">
|
3373 | <div
|
3374 | *ngIf="animations"
|
3375 | class="total-value"
|
3376 | ngx-charts-count-up
|
3377 | [countTo]="roundedTotal"
|
3378 | [valueFormatting]="valueFormatting"
|
3379 | ></div>
|
3380 | <div class="total-value" *ngIf="!animations">
|
3381 | {{ valueFormatting ? valueFormatting(roundedTotal) : defaultValueFormatting(roundedTotal) }}
|
3382 | </div>
|
3383 | <div class="total-label">
|
3384 | {{ label }}
|
3385 | </div>
|
3386 | <div class="legend-items-container">
|
3387 | <div class="legend-items">
|
3388 | <div
|
3389 | *ngFor="let legendItem of legendItems; trackBy: trackBy"
|
3390 | tabindex="-1"
|
3391 | class="legend-item"
|
3392 | (mouseenter)="activate.emit(legendItem.data)"
|
3393 | (mouseleave)="deactivate.emit(legendItem.data)"
|
3394 | (click)="select.emit(legendItem.data)"
|
3395 | >
|
3396 | <div class="item-color" [style.border-left-color]="legendItem.color"></div>
|
3397 | <div
|
3398 | *ngIf="animations"
|
3399 | class="item-value"
|
3400 | ngx-charts-count-up
|
3401 | [countTo]="legendItem._value"
|
3402 | [valueFormatting]="valueFormatting"
|
3403 | ></div>
|
3404 | <div *ngIf="!animations" class="item-value">
|
3405 | {{ valueFormatting ? valueFormatting(legendItem.value) : defaultValueFormatting(legendItem.value) }}
|
3406 | </div>
|
3407 | <div class="item-label">{{ legendItem.displayLabel }}</div>
|
3408 | <div
|
3409 | *ngIf="animations"
|
3410 | class="item-percent"
|
3411 | ngx-charts-count-up
|
3412 | [countTo]="legendItem.percentage"
|
3413 | [countSuffix]="'%'"
|
3414 | ></div>
|
3415 | <div *ngIf="!animations" class="item-percent">{{ legendItem.percentage.toLocaleString() }}%</div>
|
3416 | </div>
|
3417 | </div>
|
3418 | </div>
|
3419 | </div>
|
3420 | `,
|
3421 | encapsulation: ViewEncapsulation.None,
|
3422 | changeDetection: ChangeDetectionStrategy.OnPush,
|
3423 | 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"]
|
3424 | },] }
|
3425 | ];
|
3426 | AdvancedLegendComponent.propDecorators = {
|
3427 | width: [{ type: Input }],
|
3428 | data: [{ type: Input }],
|
3429 | colors: [{ type: Input }],
|
3430 | label: [{ type: Input }],
|
3431 | animations: [{ type: Input }],
|
3432 | select: [{ type: Output }],
|
3433 | activate: [{ type: Output }],
|
3434 | deactivate: [{ type: Output }],
|
3435 | valueFormatting: [{ type: Input }],
|
3436 | labelFormatting: [{ type: Input }],
|
3437 | percentageFormatting: [{ type: Input }]
|
3438 | };
|
3439 |
|
3440 | const COMPONENTS = [
|
3441 | AreaComponent,
|
3442 | BaseChartComponent,
|
3443 | CountUpDirective,
|
3444 | TooltipArea,
|
3445 | ChartComponent,
|
3446 | LegendComponent,
|
3447 | LegendEntryComponent,
|
3448 | ScaleLegendComponent,
|
3449 | CircleComponent,
|
3450 | CircleSeriesComponent,
|
3451 | GridPanelComponent,
|
3452 | GridPanelSeriesComponent,
|
3453 | SvgLinearGradientComponent,
|
3454 | SvgRadialGradientComponent,
|
3455 | Timeline,
|
3456 | AdvancedLegendComponent
|
3457 | ];
|
3458 | class ChartCommonModule {
|
3459 | }
|
3460 | ChartCommonModule.decorators = [
|
3461 | { type: NgModule, args: [{
|
3462 | imports: [CommonModule, AxesModule, TooltipModule],
|
3463 | declarations: [...COMPONENTS, VisibilityObserver],
|
3464 | exports: [CommonModule, AxesModule, TooltipModule, ...COMPONENTS, VisibilityObserver]
|
3465 | },] }
|
3466 | ];
|
3467 |
|
3468 | 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 }) {
|
3469 | let xOffset = margins[3];
|
3470 | let chartWidth = width;
|
3471 | let chartHeight = height - margins[0] - margins[2];
|
3472 | if (showLegend && legendPosition === LegendPosition.Right) {
|
3473 | if (legendType === ScaleType.Ordinal) {
|
3474 | columns -= 2;
|
3475 | }
|
3476 | else {
|
3477 | columns -= 1;
|
3478 | }
|
3479 | }
|
3480 | chartWidth = (chartWidth * columns) / 12;
|
3481 | chartWidth = chartWidth - margins[1] - margins[3];
|
3482 | if (showXAxis) {
|
3483 | chartHeight -= 5;
|
3484 | chartHeight -= xAxisHeight;
|
3485 | if (showXLabel) {
|
3486 |
|
3487 | const offset = 25 + 5;
|
3488 | chartHeight -= offset;
|
3489 | }
|
3490 | }
|
3491 | if (showYAxis) {
|
3492 | chartWidth -= 5;
|
3493 | chartWidth -= yAxisWidth;
|
3494 | xOffset += yAxisWidth;
|
3495 | xOffset += 10;
|
3496 | if (showYLabel) {
|
3497 |
|
3498 | const offset = 25 + 5;
|
3499 | chartWidth -= offset;
|
3500 | xOffset += offset;
|
3501 | }
|
3502 | }
|
3503 | chartWidth = Math.max(0, chartWidth);
|
3504 | chartHeight = Math.max(0, chartHeight);
|
3505 | return {
|
3506 | width: Math.floor(chartWidth),
|
3507 | height: Math.floor(chartHeight),
|
3508 | xOffset: Math.floor(xOffset)
|
3509 | };
|
3510 | }
|
3511 |
|
3512 | let colorSets = [
|
3513 | {
|
3514 | name: 'vivid',
|
3515 | selectable: true,
|
3516 | group: ScaleType.Ordinal,
|
3517 | domain: [
|
3518 | '#647c8a',
|
3519 | '#3f51b5',
|
3520 | '#2196f3',
|
3521 | '#00b862',
|
3522 | '#afdf0a',
|
3523 | '#a7b61a',
|
3524 | '#f3e562',
|
3525 | '#ff9800',
|
3526 | '#ff5722',
|
3527 | '#ff4514'
|
3528 | ]
|
3529 | },
|
3530 | {
|
3531 | name: 'natural',
|
3532 | selectable: true,
|
3533 | group: ScaleType.Ordinal,
|
3534 | domain: [
|
3535 | '#bf9d76',
|
3536 | '#e99450',
|
3537 | '#d89f59',
|
3538 | '#f2dfa7',
|
3539 | '#a5d7c6',
|
3540 | '#7794b1',
|
3541 | '#afafaf',
|
3542 | '#707160',
|
3543 | '#ba9383',
|
3544 | '#d9d5c3'
|
3545 | ]
|
3546 | },
|
3547 | {
|
3548 | name: 'cool',
|
3549 | selectable: true,
|
3550 | group: ScaleType.Ordinal,
|
3551 | domain: [
|
3552 | '#a8385d',
|
3553 | '#7aa3e5',
|
3554 | '#a27ea8',
|
3555 | '#aae3f5',
|
3556 | '#adcded',
|
3557 | '#a95963',
|
3558 | '#8796c0',
|
3559 | '#7ed3ed',
|
3560 | '#50abcc',
|
3561 | '#ad6886'
|
3562 | ]
|
3563 | },
|
3564 | {
|
3565 | name: 'fire',
|
3566 | selectable: true,
|
3567 | group: ScaleType.Ordinal,
|
3568 | domain: ['#ff3d00', '#bf360c', '#ff8f00', '#ff6f00', '#ff5722', '#e65100', '#ffca28', '#ffab00']
|
3569 | },
|
3570 | {
|
3571 | name: 'solar',
|
3572 | selectable: true,
|
3573 | group: ScaleType.Linear,
|
3574 | domain: [
|
3575 | '#fff8e1',
|
3576 | '#ffecb3',
|
3577 | '#ffe082',
|
3578 | '#ffd54f',
|
3579 | '#ffca28',
|
3580 | '#ffc107',
|
3581 | '#ffb300',
|
3582 | '#ffa000',
|
3583 | '#ff8f00',
|
3584 | '#ff6f00'
|
3585 | ]
|
3586 | },
|
3587 | {
|
3588 | name: 'air',
|
3589 | selectable: true,
|
3590 | group: ScaleType.Linear,
|
3591 | domain: [
|
3592 | '#e1f5fe',
|
3593 | '#b3e5fc',
|
3594 | '#81d4fa',
|
3595 | '#4fc3f7',
|
3596 | '#29b6f6',
|
3597 | '#03a9f4',
|
3598 | '#039be5',
|
3599 | '#0288d1',
|
3600 | '#0277bd',
|
3601 | '#01579b'
|
3602 | ]
|
3603 | },
|
3604 | {
|
3605 | name: 'aqua',
|
3606 | selectable: true,
|
3607 | group: ScaleType.Linear,
|
3608 | domain: [
|
3609 | '#e0f7fa',
|
3610 | '#b2ebf2',
|
3611 | '#80deea',
|
3612 | '#4dd0e1',
|
3613 | '#26c6da',
|
3614 | '#00bcd4',
|
3615 | '#00acc1',
|
3616 | '#0097a7',
|
3617 | '#00838f',
|
3618 | '#006064'
|
3619 | ]
|
3620 | },
|
3621 | {
|
3622 | name: 'flame',
|
3623 | selectable: false,
|
3624 | group: ScaleType.Ordinal,
|
3625 | domain: [
|
3626 | '#A10A28',
|
3627 | '#D3342D',
|
3628 | '#EF6D49',
|
3629 | '#FAAD67',
|
3630 | '#FDDE90',
|
3631 | '#DBED91',
|
3632 | '#A9D770',
|
3633 | '#6CBA67',
|
3634 | '#2C9653',
|
3635 | '#146738'
|
3636 | ]
|
3637 | },
|
3638 | {
|
3639 | name: 'ocean',
|
3640 | selectable: false,
|
3641 | group: ScaleType.Ordinal,
|
3642 | domain: [
|
3643 | '#1D68FB',
|
3644 | '#33C0FC',
|
3645 | '#4AFFFE',
|
3646 | '#AFFFFF',
|
3647 | '#FFFC63',
|
3648 | '#FDBD2D',
|
3649 | '#FC8A25',
|
3650 | '#FA4F1E',
|
3651 | '#FA141B',
|
3652 | '#BA38D1'
|
3653 | ]
|
3654 | },
|
3655 | {
|
3656 | name: 'forest',
|
3657 | selectable: false,
|
3658 | group: ScaleType.Ordinal,
|
3659 | domain: [
|
3660 | '#55C22D',
|
3661 | '#C1F33D',
|
3662 | '#3CC099',
|
3663 | '#AFFFFF',
|
3664 | '#8CFC9D',
|
3665 | '#76CFFA',
|
3666 | '#BA60FB',
|
3667 | '#EE6490',
|
3668 | '#C42A1C',
|
3669 | '#FC9F32'
|
3670 | ]
|
3671 | },
|
3672 | {
|
3673 | name: 'horizon',
|
3674 | selectable: false,
|
3675 | group: ScaleType.Ordinal,
|
3676 | domain: [
|
3677 | '#2597FB',
|
3678 | '#65EBFD',
|
3679 | '#99FDD0',
|
3680 | '#FCEE4B',
|
3681 | '#FEFCFA',
|
3682 | '#FDD6E3',
|
3683 | '#FCB1A8',
|
3684 | '#EF6F7B',
|
3685 | '#CB96E8',
|
3686 | '#EFDEE0'
|
3687 | ]
|
3688 | },
|
3689 | {
|
3690 | name: 'neons',
|
3691 | selectable: false,
|
3692 | group: ScaleType.Ordinal,
|
3693 | domain: [
|
3694 | '#FF3333',
|
3695 | '#FF33FF',
|
3696 | '#CC33FF',
|
3697 | '#0000FF',
|
3698 | '#33CCFF',
|
3699 | '#33FFFF',
|
3700 | '#33FF66',
|
3701 | '#CCFF33',
|
3702 | '#FFCC00',
|
3703 | '#FF6600'
|
3704 | ]
|
3705 | },
|
3706 | {
|
3707 | name: 'picnic',
|
3708 | selectable: false,
|
3709 | group: ScaleType.Ordinal,
|
3710 | domain: [
|
3711 | '#FAC51D',
|
3712 | '#66BD6D',
|
3713 | '#FAA026',
|
3714 | '#29BB9C',
|
3715 | '#E96B56',
|
3716 | '#55ACD2',
|
3717 | '#B7332F',
|
3718 | '#2C83C9',
|
3719 | '#9166B8',
|
3720 | '#92E7E8'
|
3721 | ]
|
3722 | },
|
3723 | {
|
3724 | name: 'night',
|
3725 | selectable: false,
|
3726 | group: ScaleType.Ordinal,
|
3727 | domain: [
|
3728 | '#2B1B5A',
|
3729 | '#501356',
|
3730 | '#183356',
|
3731 | '#28203F',
|
3732 | '#391B3C',
|
3733 | '#1E2B3C',
|
3734 | '#120634',
|
3735 | '#2D0432',
|
3736 | '#051932',
|
3737 | '#453080',
|
3738 | '#75267D',
|
3739 | '#2C507D',
|
3740 | '#4B3880',
|
3741 | '#752F7D',
|
3742 | '#35547D'
|
3743 | ]
|
3744 | },
|
3745 | {
|
3746 | name: 'nightLights',
|
3747 | selectable: false,
|
3748 | group: ScaleType.Ordinal,
|
3749 | domain: [
|
3750 | '#4e31a5',
|
3751 | '#9c25a7',
|
3752 | '#3065ab',
|
3753 | '#57468b',
|
3754 | '#904497',
|
3755 | '#46648b',
|
3756 | '#32118d',
|
3757 | '#a00fb3',
|
3758 | '#1052a2',
|
3759 | '#6e51bd',
|
3760 | '#b63cc3',
|
3761 | '#6c97cb',
|
3762 | '#8671c1',
|
3763 | '#b455be',
|
3764 | '#7496c3'
|
3765 | ]
|
3766 | }
|
3767 | ];
|
3768 |
|
3769 | class ColorHelper {
|
3770 | constructor(scheme, type, domain, customColors) {
|
3771 | if (typeof scheme === 'string') {
|
3772 | scheme = colorSets.find(cs => {
|
3773 | return cs.name === scheme;
|
3774 | });
|
3775 | }
|
3776 | this.colorDomain = scheme.domain;
|
3777 | this.scaleType = type;
|
3778 | this.domain = domain;
|
3779 | this.customColors = customColors;
|
3780 | this.scale = this.generateColorScheme(scheme, type, this.domain);
|
3781 | }
|
3782 | generateColorScheme(scheme, type, domain) {
|
3783 | if (typeof scheme === 'string') {
|
3784 | scheme = colorSets.find(cs => {
|
3785 | return cs.name === scheme;
|
3786 | });
|
3787 | }
|
3788 | let colorScale;
|
3789 | switch (type) {
|
3790 | case ScaleType.Quantile:
|
3791 | colorScale = scaleQuantile()
|
3792 | .range(scheme.domain)
|
3793 | .domain(domain);
|
3794 | break;
|
3795 | case ScaleType.Ordinal:
|
3796 | colorScale = scaleOrdinal()
|
3797 | .range(scheme.domain)
|
3798 | .domain(domain);
|
3799 | break;
|
3800 | case ScaleType.Linear:
|
3801 | {
|
3802 | const colorDomain = [...scheme.domain];
|
3803 | if (colorDomain.length === 1) {
|
3804 | colorDomain.push(colorDomain[0]);
|
3805 | this.colorDomain = colorDomain;
|
3806 | }
|
3807 | const points = range(0, 1, 1.0 / colorDomain.length);
|
3808 | colorScale = scaleLinear()
|
3809 | .range(colorDomain)
|
3810 | .domain(points);
|
3811 | }
|
3812 | break;
|
3813 | default:
|
3814 | break;
|
3815 | }
|
3816 | return colorScale;
|
3817 | }
|
3818 | getColor(value) {
|
3819 | if (value === undefined || value === null) {
|
3820 | throw new Error('Value can not be null');
|
3821 | }
|
3822 | if (this.scaleType === ScaleType.Linear) {
|
3823 | const valueScale = scaleLinear()
|
3824 | .domain(this.domain)
|
3825 | .range([0, 1]);
|
3826 | return this.scale(valueScale(value));
|
3827 | }
|
3828 | else {
|
3829 | if (typeof this.customColors === 'function') {
|
3830 | return this.customColors(value);
|
3831 | }
|
3832 | const formattedValue = value.toString();
|
3833 | let found;
|
3834 | if (this.customColors && this.customColors.length > 0) {
|
3835 | found = this.customColors.find(mapping => {
|
3836 | return mapping.name.toLowerCase() === formattedValue.toLowerCase();
|
3837 | });
|
3838 | }
|
3839 | if (found) {
|
3840 | return found.value;
|
3841 | }
|
3842 | else {
|
3843 | return this.scale(value);
|
3844 | }
|
3845 | }
|
3846 | }
|
3847 | getLinearGradientStops(value, start) {
|
3848 | if (start === undefined) {
|
3849 | start = this.domain[0];
|
3850 | }
|
3851 | const valueScale = scaleLinear()
|
3852 | .domain(this.domain)
|
3853 | .range([0, 1]);
|
3854 | const colorValueScale = scaleBand().domain(this.colorDomain).range([0, 1]);
|
3855 | const endColor = this.getColor(value);
|
3856 |
|
3857 | const startVal = valueScale(start);
|
3858 | const startColor = this.getColor(start);
|
3859 | const endVal = valueScale(value);
|
3860 | let i = 1;
|
3861 | let currentVal = startVal;
|
3862 | const stops = [];
|
3863 | stops.push({
|
3864 | color: startColor,
|
3865 | offset: startVal,
|
3866 | originalOffset: startVal,
|
3867 | opacity: 1
|
3868 | });
|
3869 | while (currentVal < endVal && i < this.colorDomain.length) {
|
3870 | const color = this.colorDomain[i];
|
3871 | const offset = colorValueScale(color);
|
3872 | if (offset <= startVal) {
|
3873 | i++;
|
3874 | continue;
|
3875 | }
|
3876 | if (offset.toFixed(4) >= (endVal - colorValueScale.bandwidth()).toFixed(4)) {
|
3877 | break;
|
3878 | }
|
3879 | stops.push({
|
3880 | color,
|
3881 | offset,
|
3882 | opacity: 1
|
3883 | });
|
3884 | currentVal = offset;
|
3885 | i++;
|
3886 | }
|
3887 | if (stops[stops.length - 1].offset < 100) {
|
3888 | stops.push({
|
3889 | color: endColor,
|
3890 | offset: endVal,
|
3891 | opacity: 1
|
3892 | });
|
3893 | }
|
3894 | if (endVal === startVal) {
|
3895 | stops[0].offset = 0;
|
3896 | stops[1].offset = 100;
|
3897 | }
|
3898 | else {
|
3899 |
|
3900 | if (stops[stops.length - 1].offset !== 100) {
|
3901 | for (const s of stops) {
|
3902 | s.offset = ((s.offset - startVal) / (endVal - startVal)) * 100;
|
3903 | }
|
3904 | }
|
3905 | }
|
3906 | return stops;
|
3907 | }
|
3908 | }
|
3909 |
|
3910 |
|
3911 |
|
3912 |
|
3913 |
|
3914 |
|
3915 |
|
3916 | function getUniqueXDomainValues(results) {
|
3917 | const valueSet = new Set();
|
3918 | for (const result of results) {
|
3919 | for (const d of result.series) {
|
3920 | valueSet.add(d.name);
|
3921 | }
|
3922 | }
|
3923 | return Array.from(valueSet);
|
3924 | }
|
3925 |
|
3926 |
|
3927 |
|
3928 |
|
3929 | function getScaleType(values, checkDateType = true) {
|
3930 | if (checkDateType) {
|
3931 | const allDates = values.every(value => value instanceof Date);
|
3932 | if (allDates) {
|
3933 | return ScaleType.Time;
|
3934 | }
|
3935 | }
|
3936 | const allNumbers = values.every(value => typeof value === 'number');
|
3937 | if (allNumbers) {
|
3938 | return ScaleType.Linear;
|
3939 | }
|
3940 | return ScaleType.Ordinal;
|
3941 | }
|
3942 | function getXDomainArray(values, xScaleMin, xScaleMax) {
|
3943 | const scaleType = getScaleType(values);
|
3944 | let xSet = [];
|
3945 | let domain = [];
|
3946 | if (scaleType === ScaleType.Linear) {
|
3947 | values = values.map(v => Number(v));
|
3948 | }
|
3949 | let min;
|
3950 | let max;
|
3951 | if (scaleType === ScaleType.Time || scaleType === ScaleType.Linear) {
|
3952 | const mappedValues = values.map(v => Number(v));
|
3953 | min = xScaleMin ? xScaleMin : Math.min(...mappedValues);
|
3954 | max = xScaleMax ? xScaleMax : Math.max(...mappedValues);
|
3955 | }
|
3956 | if (scaleType === ScaleType.Time) {
|
3957 | domain = [new Date(min), new Date(max)];
|
3958 | xSet = [...values].sort((a, b) => {
|
3959 | const aDate = a.getTime();
|
3960 | const bDate = b.getTime();
|
3961 | if (aDate > bDate)
|
3962 | return 1;
|
3963 | if (bDate > aDate)
|
3964 | return -1;
|
3965 | return 0;
|
3966 | });
|
3967 | }
|
3968 | else if (scaleType === ScaleType.Linear) {
|
3969 | domain = [min, max];
|
3970 |
|
3971 | xSet = [...values].sort((a, b) => a - b);
|
3972 | }
|
3973 | else {
|
3974 | domain = values;
|
3975 | xSet = values;
|
3976 | }
|
3977 | return { domain, xSet, scaleType };
|
3978 | }
|
3979 |
|
3980 | class AreaChartComponent extends BaseChartComponent {
|
3981 | constructor() {
|
3982 | super(...arguments);
|
3983 | this.legend = false;
|
3984 | this.legendTitle = 'Legend';
|
3985 | this.legendPosition = LegendPosition.Right;
|
3986 | this.xAxis = false;
|
3987 | this.yAxis = false;
|
3988 | this.baseValue = 'auto';
|
3989 | this.autoScale = false;
|
3990 | this.timeline = false;
|
3991 | this.showGridLines = true;
|
3992 | this.curve = curveLinear;
|
3993 | this.activeEntries = [];
|
3994 | this.trimXAxisTicks = true;
|
3995 | this.trimYAxisTicks = true;
|
3996 | this.rotateXAxisTicks = true;
|
3997 | this.maxXAxisTickLength = 16;
|
3998 | this.maxYAxisTickLength = 16;
|
3999 | this.roundDomains = false;
|
4000 | this.tooltipDisabled = false;
|
4001 | this.activate = new EventEmitter();
|
4002 | this.deactivate = new EventEmitter();
|
4003 | this.margin = [10, 20, 10, 20];
|
4004 | this.xAxisHeight = 0;
|
4005 | this.yAxisWidth = 0;
|
4006 | this.timelineHeight = 50;
|
4007 | this.timelinePadding = 10;
|
4008 | this.trackBy = (index, item) => {
|
4009 | return item.name;
|
4010 | };
|
4011 | }
|
4012 | update() {
|
4013 | super.update();
|
4014 | this.dims = calculateViewDimensions({
|
4015 | width: this.width,
|
4016 | height: this.height,
|
4017 | margins: this.margin,
|
4018 | showXAxis: this.xAxis,
|
4019 | showYAxis: this.yAxis,
|
4020 | xAxisHeight: this.xAxisHeight,
|
4021 | yAxisWidth: this.yAxisWidth,
|
4022 | showXLabel: this.showXAxisLabel,
|
4023 | showYLabel: this.showYAxisLabel,
|
4024 | showLegend: this.legend,
|
4025 | legendType: this.schemeType,
|
4026 | legendPosition: this.legendPosition
|
4027 | });
|
4028 | if (this.timeline) {
|
4029 | this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
4030 | }
|
4031 | this.xDomain = this.getXDomain();
|
4032 | if (this.filteredDomain) {
|
4033 | this.xDomain = this.filteredDomain;
|
4034 | }
|
4035 | this.yDomain = this.getYDomain();
|
4036 | this.seriesDomain = this.getSeriesDomain();
|
4037 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
4038 | this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
4039 | this.updateTimeline();
|
4040 | this.setColors();
|
4041 | this.legendOptions = this.getLegendOptions();
|
4042 | this.transform = `translate(${this.dims.xOffset}, ${this.margin[0]})`;
|
4043 | this.clipPathId = 'clip' + id().toString();
|
4044 | this.clipPath = `url(#${this.clipPathId})`;
|
4045 | }
|
4046 | updateTimeline() {
|
4047 | if (this.timeline) {
|
4048 | this.timelineWidth = this.dims.width;
|
4049 | this.timelineXDomain = this.getXDomain();
|
4050 | this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
4051 | this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
4052 | this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
4053 | }
|
4054 | }
|
4055 | getXDomain() {
|
4056 | let values = getUniqueXDomainValues(this.results);
|
4057 | this.scaleType = getScaleType(values);
|
4058 | let domain = [];
|
4059 | if (this.scaleType === ScaleType.Linear) {
|
4060 | values = values.map(v => Number(v));
|
4061 | }
|
4062 | let min;
|
4063 | let max;
|
4064 | if (this.scaleType === ScaleType.Time || this.scaleType === ScaleType.Linear) {
|
4065 | min = this.xScaleMin ? this.xScaleMin : Math.min(...values);
|
4066 | max = this.xScaleMax ? this.xScaleMax : Math.max(...values);
|
4067 | }
|
4068 | if (this.scaleType === ScaleType.Time) {
|
4069 | domain = [new Date(min), new Date(max)];
|
4070 | this.xSet = [...values].sort((a, b) => {
|
4071 | const aDate = a.getTime();
|
4072 | const bDate = b.getTime();
|
4073 | if (aDate > bDate)
|
4074 | return 1;
|
4075 | if (bDate > aDate)
|
4076 | return -1;
|
4077 | return 0;
|
4078 | });
|
4079 | }
|
4080 | else if (this.scaleType === ScaleType.Linear) {
|
4081 | domain = [min, max];
|
4082 |
|
4083 | this.xSet = [...values].sort((a, b) => a - b);
|
4084 | }
|
4085 | else {
|
4086 | domain = values;
|
4087 | this.xSet = values;
|
4088 | }
|
4089 | return domain;
|
4090 | }
|
4091 | getYDomain() {
|
4092 | const domain = [];
|
4093 | for (const results of this.results) {
|
4094 | for (const d of results.series) {
|
4095 | if (!domain.includes(d.value)) {
|
4096 | domain.push(d.value);
|
4097 | }
|
4098 | }
|
4099 | }
|
4100 | const values = [...domain];
|
4101 | if (!this.autoScale) {
|
4102 | values.push(0);
|
4103 | }
|
4104 | if (this.baseValue !== 'auto') {
|
4105 | values.push(this.baseValue);
|
4106 | }
|
4107 | const min = this.yScaleMin ? this.yScaleMin : Math.min(...values);
|
4108 | const max = this.yScaleMax ? this.yScaleMax : Math.max(...values);
|
4109 | return [min, max];
|
4110 | }
|
4111 | getSeriesDomain() {
|
4112 | return this.results.map(d => d.name);
|
4113 | }
|
4114 | getXScale(domain, width) {
|
4115 | let scale;
|
4116 | if (this.scaleType === ScaleType.Time) {
|
4117 | scale = scaleTime();
|
4118 | }
|
4119 | else if (this.scaleType === ScaleType.Linear) {
|
4120 | scale = scaleLinear();
|
4121 | }
|
4122 | else if (this.scaleType === ScaleType.Ordinal) {
|
4123 | scale = scalePoint().padding(0.1);
|
4124 | }
|
4125 | scale.range([0, width]).domain(domain);
|
4126 | return this.roundDomains ? scale.nice() : scale;
|
4127 | }
|
4128 | getYScale(domain, height) {
|
4129 | const scale = scaleLinear().range([height, 0]).domain(domain);
|
4130 | return this.roundDomains ? scale.nice() : scale;
|
4131 | }
|
4132 | getScaleType(values) {
|
4133 | let date = true;
|
4134 | let num = true;
|
4135 | for (const value of values) {
|
4136 | if (isDate(value)) {
|
4137 | date = false;
|
4138 | }
|
4139 | if (isNumber(value)) {
|
4140 | num = false;
|
4141 | }
|
4142 | }
|
4143 | if (date) {
|
4144 | return ScaleType.Time;
|
4145 | }
|
4146 | if (num) {
|
4147 | return ScaleType.Linear;
|
4148 | }
|
4149 | return ScaleType.Ordinal;
|
4150 | }
|
4151 | updateDomain(domain) {
|
4152 | this.filteredDomain = domain;
|
4153 | this.xDomain = this.filteredDomain;
|
4154 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
4155 | }
|
4156 | updateHoveredVertical(item) {
|
4157 | this.hoveredVertical = item.value;
|
4158 | this.deactivateAll();
|
4159 | }
|
4160 | hideCircles() {
|
4161 | this.hoveredVertical = null;
|
4162 | this.deactivateAll();
|
4163 | }
|
4164 | onClick(data, series) {
|
4165 | if (series) {
|
4166 | data.series = series.name;
|
4167 | }
|
4168 | this.select.emit(data);
|
4169 | }
|
4170 | setColors() {
|
4171 | let domain;
|
4172 | if (this.schemeType === ScaleType.Ordinal) {
|
4173 | domain = this.seriesDomain;
|
4174 | }
|
4175 | else {
|
4176 | domain = this.yDomain;
|
4177 | }
|
4178 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
4179 | }
|
4180 | getLegendOptions() {
|
4181 | const opts = {
|
4182 | scaleType: this.schemeType,
|
4183 | colors: undefined,
|
4184 | domain: [],
|
4185 | title: undefined,
|
4186 | position: this.legendPosition
|
4187 | };
|
4188 | if (opts.scaleType === ScaleType.Ordinal) {
|
4189 | opts.domain = this.seriesDomain;
|
4190 | opts.colors = this.colors;
|
4191 | opts.title = this.legendTitle;
|
4192 | }
|
4193 | else {
|
4194 | opts.domain = this.yDomain;
|
4195 | opts.colors = this.colors.scale;
|
4196 | }
|
4197 | return opts;
|
4198 | }
|
4199 | updateYAxisWidth({ width }) {
|
4200 | this.yAxisWidth = width;
|
4201 | this.update();
|
4202 | }
|
4203 | updateXAxisHeight({ height }) {
|
4204 | this.xAxisHeight = height;
|
4205 | this.update();
|
4206 | }
|
4207 | onActivate(item) {
|
4208 | const idx = this.activeEntries.findIndex(d => {
|
4209 | return d.name === item.name && d.value === item.value;
|
4210 | });
|
4211 | if (idx > -1) {
|
4212 | return;
|
4213 | }
|
4214 | this.activeEntries = [item, ...this.activeEntries];
|
4215 | this.activate.emit({ value: item, entries: this.activeEntries });
|
4216 | }
|
4217 | onDeactivate(item) {
|
4218 | const idx = this.activeEntries.findIndex(d => {
|
4219 | return d.name === item.name && d.value === item.value;
|
4220 | });
|
4221 | this.activeEntries.splice(idx, 1);
|
4222 | this.activeEntries = [...this.activeEntries];
|
4223 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
4224 | }
|
4225 | deactivateAll() {
|
4226 | this.activeEntries = [...this.activeEntries];
|
4227 | for (const entry of this.activeEntries) {
|
4228 | this.deactivate.emit({ value: entry, entries: [] });
|
4229 | }
|
4230 | this.activeEntries = [];
|
4231 | }
|
4232 | }
|
4233 | AreaChartComponent.decorators = [
|
4234 | { type: Component, args: [{
|
4235 | selector: 'ngx-charts-area-chart',
|
4236 | template: `
|
4237 | <ngx-charts-chart
|
4238 | [view]="[width, height]"
|
4239 | [showLegend]="legend"
|
4240 | [legendOptions]="legendOptions"
|
4241 | [activeEntries]="activeEntries"
|
4242 | [animations]="animations"
|
4243 | (legendLabelClick)="onClick($event)"
|
4244 | (legendLabelActivate)="onActivate($event)"
|
4245 | (legendLabelDeactivate)="onDeactivate($event)"
|
4246 | >
|
4247 | <svg:defs>
|
4248 | <svg:clipPath [attr.id]="clipPathId">
|
4249 | <svg:rect
|
4250 | [attr.width]="dims.width + 10"
|
4251 | [attr.height]="dims.height + 10"
|
4252 | [attr.transform]="'translate(-5, -5)'"
|
4253 | />
|
4254 | </svg:clipPath>
|
4255 | </svg:defs>
|
4256 | <svg:g [attr.transform]="transform" class="area-chart chart">
|
4257 | <svg:g
|
4258 | ngx-charts-x-axis
|
4259 | *ngIf="xAxis"
|
4260 | [xScale]="xScale"
|
4261 | [dims]="dims"
|
4262 | [showGridLines]="showGridLines"
|
4263 | [showLabel]="showXAxisLabel"
|
4264 | [labelText]="xAxisLabel"
|
4265 | [trimTicks]="trimXAxisTicks"
|
4266 | [rotateTicks]="rotateXAxisTicks"
|
4267 | [maxTickLength]="maxXAxisTickLength"
|
4268 | [tickFormatting]="xAxisTickFormatting"
|
4269 | [ticks]="xAxisTicks"
|
4270 | (dimensionsChanged)="updateXAxisHeight($event)"
|
4271 | ></svg:g>
|
4272 | <svg:g
|
4273 | ngx-charts-y-axis
|
4274 | *ngIf="yAxis"
|
4275 | [yScale]="yScale"
|
4276 | [dims]="dims"
|
4277 | [showGridLines]="showGridLines"
|
4278 | [showLabel]="showYAxisLabel"
|
4279 | [labelText]="yAxisLabel"
|
4280 | [trimTicks]="trimYAxisTicks"
|
4281 | [maxTickLength]="maxYAxisTickLength"
|
4282 | [tickFormatting]="yAxisTickFormatting"
|
4283 | [ticks]="yAxisTicks"
|
4284 | (dimensionsChanged)="updateYAxisWidth($event)"
|
4285 | ></svg:g>
|
4286 | <svg:g [attr.clip-path]="clipPath">
|
4287 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
4288 | <svg:g
|
4289 | ngx-charts-area-series
|
4290 | [xScale]="xScale"
|
4291 | [yScale]="yScale"
|
4292 | [baseValue]="baseValue"
|
4293 | [colors]="colors"
|
4294 | [data]="series"
|
4295 | [activeEntries]="activeEntries"
|
4296 | [scaleType]="scaleType"
|
4297 | [gradient]="gradient"
|
4298 | [curve]="curve"
|
4299 | [animations]="animations"
|
4300 | />
|
4301 | </svg:g>
|
4302 |
|
4303 | <svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
4304 | <svg:g
|
4305 | ngx-charts-tooltip-area
|
4306 | [dims]="dims"
|
4307 | [xSet]="xSet"
|
4308 | [xScale]="xScale"
|
4309 | [yScale]="yScale"
|
4310 | [results]="results"
|
4311 | [colors]="colors"
|
4312 | [tooltipDisabled]="tooltipDisabled"
|
4313 | [tooltipTemplate]="seriesTooltipTemplate"
|
4314 | (hover)="updateHoveredVertical($event)"
|
4315 | />
|
4316 |
|
4317 | <svg:g *ngFor="let series of results">
|
4318 | <svg:g
|
4319 | ngx-charts-circle-series
|
4320 | [xScale]="xScale"
|
4321 | [yScale]="yScale"
|
4322 | [colors]="colors"
|
4323 | [activeEntries]="activeEntries"
|
4324 | [data]="series"
|
4325 | [scaleType]="scaleType"
|
4326 | [visibleValue]="hoveredVertical"
|
4327 | [tooltipDisabled]="tooltipDisabled"
|
4328 | [tooltipTemplate]="tooltipTemplate"
|
4329 | (select)="onClick($event, series)"
|
4330 | (activate)="onActivate($event)"
|
4331 | (deactivate)="onDeactivate($event)"
|
4332 | />
|
4333 | </svg:g>
|
4334 | </svg:g>
|
4335 | </svg:g>
|
4336 | </svg:g>
|
4337 | <svg:g
|
4338 | ngx-charts-timeline
|
4339 | *ngIf="timeline && scaleType != 'ordinal'"
|
4340 | [attr.transform]="timelineTransform"
|
4341 | [results]="results"
|
4342 | [view]="[timelineWidth, height]"
|
4343 | [height]="timelineHeight"
|
4344 | [scheme]="scheme"
|
4345 | [customColors]="customColors"
|
4346 | [legend]="legend"
|
4347 | [scaleType]="scaleType"
|
4348 | (onDomainChange)="updateDomain($event)"
|
4349 | >
|
4350 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
4351 | <svg:g
|
4352 | ngx-charts-area-series
|
4353 | [xScale]="timelineXScale"
|
4354 | [yScale]="timelineYScale"
|
4355 | [baseValue]="baseValue"
|
4356 | [colors]="colors"
|
4357 | [data]="series"
|
4358 | [scaleType]="scaleType"
|
4359 | [gradient]="gradient"
|
4360 | [curve]="curve"
|
4361 | [animations]="animations"
|
4362 | />
|
4363 | </svg:g>
|
4364 | </svg:g>
|
4365 | </ngx-charts-chart>
|
4366 | `,
|
4367 | changeDetection: ChangeDetectionStrategy.OnPush,
|
4368 | encapsulation: ViewEncapsulation.None,
|
4369 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
4370 | },] }
|
4371 | ];
|
4372 | AreaChartComponent.propDecorators = {
|
4373 | legend: [{ type: Input }],
|
4374 | legendTitle: [{ type: Input }],
|
4375 | legendPosition: [{ type: Input }],
|
4376 | xAxis: [{ type: Input }],
|
4377 | yAxis: [{ type: Input }],
|
4378 | baseValue: [{ type: Input }],
|
4379 | autoScale: [{ type: Input }],
|
4380 | showXAxisLabel: [{ type: Input }],
|
4381 | showYAxisLabel: [{ type: Input }],
|
4382 | xAxisLabel: [{ type: Input }],
|
4383 | yAxisLabel: [{ type: Input }],
|
4384 | timeline: [{ type: Input }],
|
4385 | gradient: [{ type: Input }],
|
4386 | showGridLines: [{ type: Input }],
|
4387 | curve: [{ type: Input }],
|
4388 | activeEntries: [{ type: Input }],
|
4389 | schemeType: [{ type: Input }],
|
4390 | trimXAxisTicks: [{ type: Input }],
|
4391 | trimYAxisTicks: [{ type: Input }],
|
4392 | rotateXAxisTicks: [{ type: Input }],
|
4393 | maxXAxisTickLength: [{ type: Input }],
|
4394 | maxYAxisTickLength: [{ type: Input }],
|
4395 | xAxisTickFormatting: [{ type: Input }],
|
4396 | yAxisTickFormatting: [{ type: Input }],
|
4397 | xAxisTicks: [{ type: Input }],
|
4398 | yAxisTicks: [{ type: Input }],
|
4399 | roundDomains: [{ type: Input }],
|
4400 | tooltipDisabled: [{ type: Input }],
|
4401 | xScaleMin: [{ type: Input }],
|
4402 | xScaleMax: [{ type: Input }],
|
4403 | yScaleMin: [{ type: Input }],
|
4404 | yScaleMax: [{ type: Input }],
|
4405 | activate: [{ type: Output }],
|
4406 | deactivate: [{ type: Output }],
|
4407 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
4408 | seriesTooltipTemplate: [{ type: ContentChild, args: ['seriesTooltipTemplate',] }],
|
4409 | hideCircles: [{ type: HostListener, args: ['mouseleave',] }]
|
4410 | };
|
4411 |
|
4412 | class AreaChartNormalizedComponent extends BaseChartComponent {
|
4413 | constructor() {
|
4414 | super(...arguments);
|
4415 | this.legend = false;
|
4416 | this.legendTitle = 'Legend';
|
4417 | this.legendPosition = LegendPosition.Right;
|
4418 | this.showXAxisLabel = false;
|
4419 | this.showYAxisLabel = false;
|
4420 | this.showGridLines = true;
|
4421 | this.curve = curveLinear;
|
4422 | this.activeEntries = [];
|
4423 | this.trimXAxisTicks = true;
|
4424 | this.trimYAxisTicks = true;
|
4425 | this.rotateXAxisTicks = true;
|
4426 | this.maxXAxisTickLength = 16;
|
4427 | this.maxYAxisTickLength = 16;
|
4428 | this.roundDomains = false;
|
4429 | this.tooltipDisabled = false;
|
4430 | this.activate = new EventEmitter();
|
4431 | this.deactivate = new EventEmitter();
|
4432 | this.yDomain = [0, 100];
|
4433 | this.margin = [10, 20, 10, 20];
|
4434 | this.xAxisHeight = 0;
|
4435 | this.yAxisWidth = 0;
|
4436 | this.seriesType = SeriesType;
|
4437 | this.timelineHeight = 50;
|
4438 | this.timelinePadding = 10;
|
4439 | this.trackBy = (index, item) => {
|
4440 | return item.name;
|
4441 | };
|
4442 | }
|
4443 | update() {
|
4444 | super.update();
|
4445 | this.dims = calculateViewDimensions({
|
4446 | width: this.width,
|
4447 | height: this.height,
|
4448 | margins: this.margin,
|
4449 | showXAxis: this.xAxis,
|
4450 | showYAxis: this.yAxis,
|
4451 | xAxisHeight: this.xAxisHeight,
|
4452 | yAxisWidth: this.yAxisWidth,
|
4453 | showXLabel: this.showXAxisLabel,
|
4454 | showYLabel: this.showYAxisLabel,
|
4455 | showLegend: this.legend,
|
4456 | legendType: this.schemeType,
|
4457 | legendPosition: this.legendPosition
|
4458 | });
|
4459 | if (this.timeline) {
|
4460 | this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
4461 | }
|
4462 | this.xDomain = this.getXDomain();
|
4463 | if (this.filteredDomain) {
|
4464 | this.xDomain = this.filteredDomain;
|
4465 | }
|
4466 | this.seriesDomain = this.getSeriesDomain();
|
4467 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
4468 | this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
4469 | for (let i = 0; i < this.xSet.length; i++) {
|
4470 | const val = this.xSet[i];
|
4471 | let d0 = 0;
|
4472 | let total = 0;
|
4473 | for (const group of this.results) {
|
4474 | const d = group.series.find(item => {
|
4475 | let a = item.name;
|
4476 | let b = val;
|
4477 | if (this.scaleType === ScaleType.Time) {
|
4478 | a = a.valueOf();
|
4479 | b = b.valueOf();
|
4480 | }
|
4481 | return a === b;
|
4482 | });
|
4483 | if (d) {
|
4484 | total += d.value;
|
4485 | }
|
4486 | }
|
4487 | for (const group of this.results) {
|
4488 | let d = group.series.find(item => {
|
4489 | let a = item.name;
|
4490 | let b = val;
|
4491 | if (this.scaleType === ScaleType.Time) {
|
4492 | a = a.valueOf();
|
4493 | b = b.valueOf();
|
4494 | }
|
4495 | return a === b;
|
4496 | });
|
4497 | if (d) {
|
4498 | d.d0 = d0;
|
4499 | d.d1 = d0 + d.value;
|
4500 | d0 += d.value;
|
4501 | }
|
4502 | else {
|
4503 | d = {
|
4504 | name: val,
|
4505 | value: 0,
|
4506 | d0,
|
4507 | d1: d0
|
4508 | };
|
4509 | group.series.push(d);
|
4510 | }
|
4511 | if (total > 0) {
|
4512 | d.d0 = (d.d0 * 100) / total;
|
4513 | d.d1 = (d.d1 * 100) / total;
|
4514 | }
|
4515 | else {
|
4516 | d.d0 = 0;
|
4517 | d.d1 = 0;
|
4518 | }
|
4519 | }
|
4520 | }
|
4521 | this.updateTimeline();
|
4522 | this.setColors();
|
4523 | this.legendOptions = this.getLegendOptions();
|
4524 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
4525 | this.clipPathId = 'clip' + id().toString();
|
4526 | this.clipPath = `url(#${this.clipPathId})`;
|
4527 | }
|
4528 | updateTimeline() {
|
4529 | if (this.timeline) {
|
4530 | this.timelineWidth = this.dims.width;
|
4531 | this.timelineXDomain = this.getXDomain();
|
4532 | this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
4533 | this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
4534 | this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
4535 | }
|
4536 | }
|
4537 | getXDomain() {
|
4538 | let values = getUniqueXDomainValues(this.results);
|
4539 | this.scaleType = getScaleType(values);
|
4540 | let domain = [];
|
4541 | if (this.scaleType === ScaleType.Time) {
|
4542 | const min = Math.min(...values);
|
4543 | const max = Math.max(...values);
|
4544 | domain = [new Date(min), new Date(max)];
|
4545 | this.xSet = [...values].sort((a, b) => {
|
4546 | const aDate = a.getTime();
|
4547 | const bDate = b.getTime();
|
4548 | if (aDate > bDate)
|
4549 | return 1;
|
4550 | if (bDate > aDate)
|
4551 | return -1;
|
4552 | return 0;
|
4553 | });
|
4554 | }
|
4555 | else if (this.scaleType === ScaleType.Linear) {
|
4556 | values = values.map(v => Number(v));
|
4557 | const min = Math.min(...values);
|
4558 | const max = Math.max(...values);
|
4559 | domain = [min, max];
|
4560 |
|
4561 | this.xSet = [...values].sort((a, b) => a - b);
|
4562 | }
|
4563 | else {
|
4564 | domain = values;
|
4565 | this.xSet = values;
|
4566 | }
|
4567 | return domain;
|
4568 | }
|
4569 | getSeriesDomain() {
|
4570 | return this.results.map(d => d.name);
|
4571 | }
|
4572 | getXScale(domain, width) {
|
4573 | let scale;
|
4574 | if (this.scaleType === ScaleType.Time) {
|
4575 | scale = scaleTime();
|
4576 | }
|
4577 | else if (this.scaleType === ScaleType.Linear) {
|
4578 | scale = scaleLinear();
|
4579 | }
|
4580 | else if (this.scaleType === ScaleType.Ordinal) {
|
4581 | scale = scalePoint().padding(0.1);
|
4582 | }
|
4583 | scale.range([0, width]).domain(domain);
|
4584 | return this.roundDomains ? scale.nice() : scale;
|
4585 | }
|
4586 | getYScale(domain, height) {
|
4587 | const scale = scaleLinear().range([height, 0]).domain(domain);
|
4588 | return this.roundDomains ? scale.nice() : scale;
|
4589 | }
|
4590 | updateDomain(domain) {
|
4591 | this.filteredDomain = domain;
|
4592 | this.xDomain = this.filteredDomain;
|
4593 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
4594 | }
|
4595 | updateHoveredVertical(item) {
|
4596 | this.hoveredVertical = item.value;
|
4597 | this.deactivateAll();
|
4598 | }
|
4599 | hideCircles() {
|
4600 | this.hoveredVertical = null;
|
4601 | this.deactivateAll();
|
4602 | }
|
4603 | onClick(data, series) {
|
4604 | if (series) {
|
4605 | data.series = series.name;
|
4606 | }
|
4607 | this.select.emit(data);
|
4608 | }
|
4609 | setColors() {
|
4610 | let domain;
|
4611 | if (this.schemeType === ScaleType.Ordinal) {
|
4612 | domain = this.seriesDomain;
|
4613 | }
|
4614 | else {
|
4615 | domain = this.yDomain;
|
4616 | }
|
4617 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
4618 | }
|
4619 | getLegendOptions() {
|
4620 | const opts = {
|
4621 | scaleType: this.schemeType,
|
4622 | colors: undefined,
|
4623 | domain: [],
|
4624 | title: undefined,
|
4625 | position: this.legendPosition
|
4626 | };
|
4627 | if (opts.scaleType === ScaleType.Ordinal) {
|
4628 | opts.domain = this.seriesDomain;
|
4629 | opts.colors = this.colors;
|
4630 | opts.title = this.legendTitle;
|
4631 | }
|
4632 | else {
|
4633 | opts.domain = this.yDomain;
|
4634 | opts.colors = this.colors.scale;
|
4635 | }
|
4636 | return opts;
|
4637 | }
|
4638 | updateYAxisWidth({ width }) {
|
4639 | this.yAxisWidth = width;
|
4640 | this.update();
|
4641 | }
|
4642 | updateXAxisHeight({ height }) {
|
4643 | this.xAxisHeight = height;
|
4644 | this.update();
|
4645 | }
|
4646 | onActivate(item) {
|
4647 | const idx = this.activeEntries.findIndex(d => {
|
4648 | return d.name === item.name && d.value === item.value;
|
4649 | });
|
4650 | if (idx > -1) {
|
4651 | return;
|
4652 | }
|
4653 | this.activeEntries = [item, ...this.activeEntries];
|
4654 | this.activate.emit({ value: item, entries: this.activeEntries });
|
4655 | }
|
4656 | onDeactivate(item) {
|
4657 | const idx = this.activeEntries.findIndex(d => {
|
4658 | return d.name === item.name && d.value === item.value;
|
4659 | });
|
4660 | this.activeEntries.splice(idx, 1);
|
4661 | this.activeEntries = [...this.activeEntries];
|
4662 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
4663 | }
|
4664 | deactivateAll() {
|
4665 | this.activeEntries = [...this.activeEntries];
|
4666 | for (const entry of this.activeEntries) {
|
4667 | this.deactivate.emit({ value: entry, entries: [] });
|
4668 | }
|
4669 | this.activeEntries = [];
|
4670 | }
|
4671 | }
|
4672 | AreaChartNormalizedComponent.decorators = [
|
4673 | { type: Component, args: [{
|
4674 | selector: 'ngx-charts-area-chart-normalized',
|
4675 | template: `
|
4676 | <ngx-charts-chart
|
4677 | [view]="[width, height]"
|
4678 | [showLegend]="legend"
|
4679 | [legendOptions]="legendOptions"
|
4680 | [activeEntries]="activeEntries"
|
4681 | [animations]="animations"
|
4682 | (legendLabelClick)="onClick($event)"
|
4683 | (legendLabelActivate)="onActivate($event)"
|
4684 | (legendLabelDeactivate)="onDeactivate($event)"
|
4685 | >
|
4686 | <svg:defs>
|
4687 | <svg:clipPath [attr.id]="clipPathId">
|
4688 | <svg:rect
|
4689 | [attr.width]="dims.width + 10"
|
4690 | [attr.height]="dims.height + 10"
|
4691 | [attr.transform]="'translate(-5, -5)'"
|
4692 | />
|
4693 | </svg:clipPath>
|
4694 | </svg:defs>
|
4695 | <svg:g [attr.transform]="transform" class="area-chart chart">
|
4696 | <svg:g
|
4697 | ngx-charts-x-axis
|
4698 | *ngIf="xAxis"
|
4699 | [xScale]="xScale"
|
4700 | [dims]="dims"
|
4701 | [showGridLines]="showGridLines"
|
4702 | [showLabel]="showXAxisLabel"
|
4703 | [labelText]="xAxisLabel"
|
4704 | [trimTicks]="trimXAxisTicks"
|
4705 | [rotateTicks]="rotateXAxisTicks"
|
4706 | [maxTickLength]="maxXAxisTickLength"
|
4707 | [tickFormatting]="xAxisTickFormatting"
|
4708 | [ticks]="xAxisTicks"
|
4709 | (dimensionsChanged)="updateXAxisHeight($event)"
|
4710 | ></svg:g>
|
4711 | <svg:g
|
4712 | ngx-charts-y-axis
|
4713 | *ngIf="yAxis"
|
4714 | [yScale]="yScale"
|
4715 | [dims]="dims"
|
4716 | [showGridLines]="showGridLines"
|
4717 | [showLabel]="showYAxisLabel"
|
4718 | [labelText]="yAxisLabel"
|
4719 | [trimTicks]="trimYAxisTicks"
|
4720 | [maxTickLength]="maxYAxisTickLength"
|
4721 | [tickFormatting]="yAxisTickFormatting"
|
4722 | [ticks]="yAxisTicks"
|
4723 | (dimensionsChanged)="updateYAxisWidth($event)"
|
4724 | ></svg:g>
|
4725 | <svg:g [attr.clip-path]="clipPath">
|
4726 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
4727 | <svg:g
|
4728 | ngx-charts-area-series
|
4729 | [xScale]="xScale"
|
4730 | [yScale]="yScale"
|
4731 | [colors]="colors"
|
4732 | [data]="series"
|
4733 | [scaleType]="scaleType"
|
4734 | [activeEntries]="activeEntries"
|
4735 | [gradient]="gradient"
|
4736 | [normalized]="true"
|
4737 | [curve]="curve"
|
4738 | [animations]="animations"
|
4739 | />
|
4740 | </svg:g>
|
4741 |
|
4742 | <svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
4743 | <svg:g
|
4744 | ngx-charts-tooltip-area
|
4745 | [dims]="dims"
|
4746 | [xSet]="xSet"
|
4747 | [xScale]="xScale"
|
4748 | [yScale]="yScale"
|
4749 | [results]="results"
|
4750 | [colors]="colors"
|
4751 | [showPercentage]="true"
|
4752 | [tooltipDisabled]="tooltipDisabled"
|
4753 | [tooltipTemplate]="seriesTooltipTemplate"
|
4754 | (hover)="updateHoveredVertical($event)"
|
4755 | />
|
4756 |
|
4757 | <svg:g *ngFor="let series of results">
|
4758 | <svg:g
|
4759 | ngx-charts-circle-series
|
4760 | [type]="seriesType.Stacked"
|
4761 | [xScale]="xScale"
|
4762 | [yScale]="yScale"
|
4763 | [colors]="colors"
|
4764 | [activeEntries]="activeEntries"
|
4765 | [data]="series"
|
4766 | [scaleType]="scaleType"
|
4767 | [visibleValue]="hoveredVertical"
|
4768 | [tooltipDisabled]="tooltipDisabled"
|
4769 | [tooltipTemplate]="tooltipTemplate"
|
4770 | (select)="onClick($event, series)"
|
4771 | (activate)="onActivate($event)"
|
4772 | (deactivate)="onDeactivate($event)"
|
4773 | />
|
4774 | </svg:g>
|
4775 | </svg:g>
|
4776 | </svg:g>
|
4777 | </svg:g>
|
4778 | <svg:g
|
4779 | ngx-charts-timeline
|
4780 | *ngIf="timeline && scaleType != 'ordinal'"
|
4781 | [attr.transform]="timelineTransform"
|
4782 | [results]="results"
|
4783 | [view]="[timelineWidth, height]"
|
4784 | [height]="timelineHeight"
|
4785 | [scheme]="scheme"
|
4786 | [customColors]="customColors"
|
4787 | [legend]="legend"
|
4788 | [scaleType]="scaleType"
|
4789 | (onDomainChange)="updateDomain($event)"
|
4790 | >
|
4791 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
4792 | <svg:g
|
4793 | ngx-charts-area-series
|
4794 | [xScale]="timelineXScale"
|
4795 | [yScale]="timelineYScale"
|
4796 | [colors]="colors"
|
4797 | [data]="series"
|
4798 | [scaleType]="scaleType"
|
4799 | [gradient]="gradient"
|
4800 | [normalized]="true"
|
4801 | [curve]="curve"
|
4802 | [animations]="animations"
|
4803 | />
|
4804 | </svg:g>
|
4805 | </svg:g>
|
4806 | </ngx-charts-chart>
|
4807 | `,
|
4808 | changeDetection: ChangeDetectionStrategy.OnPush,
|
4809 | encapsulation: ViewEncapsulation.None,
|
4810 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
4811 | },] }
|
4812 | ];
|
4813 | AreaChartNormalizedComponent.propDecorators = {
|
4814 | legend: [{ type: Input }],
|
4815 | legendTitle: [{ type: Input }],
|
4816 | legendPosition: [{ type: Input }],
|
4817 | xAxis: [{ type: Input }],
|
4818 | yAxis: [{ type: Input }],
|
4819 | showXAxisLabel: [{ type: Input }],
|
4820 | showYAxisLabel: [{ type: Input }],
|
4821 | xAxisLabel: [{ type: Input }],
|
4822 | yAxisLabel: [{ type: Input }],
|
4823 | timeline: [{ type: Input }],
|
4824 | gradient: [{ type: Input }],
|
4825 | showGridLines: [{ type: Input }],
|
4826 | curve: [{ type: Input }],
|
4827 | activeEntries: [{ type: Input }],
|
4828 | schemeType: [{ type: Input }],
|
4829 | trimXAxisTicks: [{ type: Input }],
|
4830 | trimYAxisTicks: [{ type: Input }],
|
4831 | rotateXAxisTicks: [{ type: Input }],
|
4832 | maxXAxisTickLength: [{ type: Input }],
|
4833 | maxYAxisTickLength: [{ type: Input }],
|
4834 | xAxisTickFormatting: [{ type: Input }],
|
4835 | yAxisTickFormatting: [{ type: Input }],
|
4836 | xAxisTicks: [{ type: Input }],
|
4837 | yAxisTicks: [{ type: Input }],
|
4838 | roundDomains: [{ type: Input }],
|
4839 | tooltipDisabled: [{ type: Input }],
|
4840 | activate: [{ type: Output }],
|
4841 | deactivate: [{ type: Output }],
|
4842 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
4843 | seriesTooltipTemplate: [{ type: ContentChild, args: ['seriesTooltipTemplate',] }],
|
4844 | hideCircles: [{ type: HostListener, args: ['mouseleave',] }]
|
4845 | };
|
4846 |
|
4847 | class AreaChartStackedComponent extends BaseChartComponent {
|
4848 | constructor() {
|
4849 | super(...arguments);
|
4850 | this.legend = false;
|
4851 | this.legendTitle = 'Legend';
|
4852 | this.legendPosition = LegendPosition.Right;
|
4853 | this.xAxis = false;
|
4854 | this.yAxis = false;
|
4855 | this.timeline = false;
|
4856 | this.showGridLines = true;
|
4857 | this.curve = curveLinear;
|
4858 | this.activeEntries = [];
|
4859 | this.trimXAxisTicks = true;
|
4860 | this.trimYAxisTicks = true;
|
4861 | this.rotateXAxisTicks = true;
|
4862 | this.maxXAxisTickLength = 16;
|
4863 | this.maxYAxisTickLength = 16;
|
4864 | this.roundDomains = false;
|
4865 | this.tooltipDisabled = false;
|
4866 | this.activate = new EventEmitter();
|
4867 | this.deactivate = new EventEmitter();
|
4868 | this.margin = [10, 20, 10, 20];
|
4869 | this.xAxisHeight = 0;
|
4870 | this.yAxisWidth = 0;
|
4871 | this.timelineHeight = 50;
|
4872 | this.timelinePadding = 10;
|
4873 | this.seriesType = SeriesType;
|
4874 | }
|
4875 | update() {
|
4876 | super.update();
|
4877 | this.dims = calculateViewDimensions({
|
4878 | width: this.width,
|
4879 | height: this.height,
|
4880 | margins: this.margin,
|
4881 | showXAxis: this.xAxis,
|
4882 | showYAxis: this.yAxis,
|
4883 | xAxisHeight: this.xAxisHeight,
|
4884 | yAxisWidth: this.yAxisWidth,
|
4885 | showXLabel: this.showXAxisLabel,
|
4886 | showYLabel: this.showYAxisLabel,
|
4887 | showLegend: this.legend,
|
4888 | legendType: this.schemeType,
|
4889 | legendPosition: this.legendPosition
|
4890 | });
|
4891 | if (this.timeline) {
|
4892 | this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
4893 | }
|
4894 | this.xDomain = this.getXDomain();
|
4895 | if (this.filteredDomain) {
|
4896 | this.xDomain = this.filteredDomain;
|
4897 | }
|
4898 | this.yDomain = this.getYDomain();
|
4899 | this.seriesDomain = this.getSeriesDomain();
|
4900 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
4901 | this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
4902 | for (let i = 0; i < this.xSet.length; i++) {
|
4903 | const val = this.xSet[i];
|
4904 | let d0 = 0;
|
4905 | for (const group of this.results) {
|
4906 | let d = group.series.find(item => {
|
4907 | let a = item.name;
|
4908 | let b = val;
|
4909 | if (this.scaleType === ScaleType.Time) {
|
4910 | a = a.valueOf();
|
4911 | b = b.valueOf();
|
4912 | }
|
4913 | return a === b;
|
4914 | });
|
4915 | if (d) {
|
4916 | d.d0 = d0;
|
4917 | d.d1 = d0 + d.value;
|
4918 | d0 += d.value;
|
4919 | }
|
4920 | else {
|
4921 | d = {
|
4922 | name: val,
|
4923 | value: 0,
|
4924 | d0,
|
4925 | d1: d0
|
4926 | };
|
4927 | group.series.push(d);
|
4928 | }
|
4929 | }
|
4930 | }
|
4931 | this.updateTimeline();
|
4932 | this.setColors();
|
4933 | this.legendOptions = this.getLegendOptions();
|
4934 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
4935 | this.clipPathId = 'clip' + id().toString();
|
4936 | this.clipPath = `url(#${this.clipPathId})`;
|
4937 | }
|
4938 | updateTimeline() {
|
4939 | if (this.timeline) {
|
4940 | this.timelineWidth = this.dims.width;
|
4941 | this.timelineXDomain = this.getXDomain();
|
4942 | this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
4943 | this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
4944 | this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
4945 | }
|
4946 | }
|
4947 | getXDomain() {
|
4948 | let values = getUniqueXDomainValues(this.results);
|
4949 | this.scaleType = getScaleType(values);
|
4950 | let domain = [];
|
4951 | if (this.scaleType === ScaleType.Linear) {
|
4952 | values = values.map(v => Number(v));
|
4953 | }
|
4954 | let min;
|
4955 | let max;
|
4956 | if (this.scaleType === ScaleType.Time || this.scaleType === ScaleType.Linear) {
|
4957 | min = this.xScaleMin ? this.xScaleMin : Math.min(...values);
|
4958 | max = this.xScaleMax ? this.xScaleMax : Math.max(...values);
|
4959 | }
|
4960 | if (this.scaleType === ScaleType.Time) {
|
4961 | domain = [new Date(min), new Date(max)];
|
4962 | this.xSet = [...values].sort((a, b) => {
|
4963 | const aDate = a.getTime();
|
4964 | const bDate = b.getTime();
|
4965 | if (aDate > bDate)
|
4966 | return 1;
|
4967 | if (bDate > aDate)
|
4968 | return -1;
|
4969 | return 0;
|
4970 | });
|
4971 | }
|
4972 | else if (this.scaleType === ScaleType.Linear) {
|
4973 | domain = [min, max];
|
4974 |
|
4975 | this.xSet = [...values].sort((a, b) => a - b);
|
4976 | }
|
4977 | else {
|
4978 | domain = values;
|
4979 | this.xSet = values;
|
4980 | }
|
4981 | return domain;
|
4982 | }
|
4983 | getYDomain() {
|
4984 | const domain = [];
|
4985 | for (let i = 0; i < this.xSet.length; i++) {
|
4986 | const val = this.xSet[i];
|
4987 | let sum = 0;
|
4988 | for (const group of this.results) {
|
4989 | const d = group.series.find(item => {
|
4990 | let a = item.name;
|
4991 | let b = val;
|
4992 | if (this.scaleType === ScaleType.Time) {
|
4993 | a = a.valueOf();
|
4994 | b = b.valueOf();
|
4995 | }
|
4996 | return a === b;
|
4997 | });
|
4998 | if (d) {
|
4999 | sum += d.value;
|
5000 | }
|
5001 | }
|
5002 | domain.push(sum);
|
5003 | }
|
5004 | const min = this.yScaleMin ? this.yScaleMin : Math.min(0, ...domain);
|
5005 | const max = this.yScaleMax ? this.yScaleMax : Math.max(...domain);
|
5006 | return [min, max];
|
5007 | }
|
5008 | getSeriesDomain() {
|
5009 | return this.results.map(d => d.name);
|
5010 | }
|
5011 | getXScale(domain, width) {
|
5012 | let scale;
|
5013 | if (this.scaleType === ScaleType.Time) {
|
5014 | scale = scaleTime();
|
5015 | }
|
5016 | else if (this.scaleType === ScaleType.Linear) {
|
5017 | scale = scaleLinear();
|
5018 | }
|
5019 | else if (this.scaleType === ScaleType.Ordinal) {
|
5020 | scale = scalePoint().padding(0.1);
|
5021 | }
|
5022 | scale.range([0, width]).domain(domain);
|
5023 | return this.roundDomains ? scale.nice() : scale;
|
5024 | }
|
5025 | getYScale(domain, height) {
|
5026 | const scale = scaleLinear().range([height, 0]).domain(domain);
|
5027 | return this.roundDomains ? scale.nice() : scale;
|
5028 | }
|
5029 | updateDomain(domain) {
|
5030 | this.filteredDomain = domain;
|
5031 | this.xDomain = this.filteredDomain;
|
5032 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
5033 | }
|
5034 | updateHoveredVertical(item) {
|
5035 | this.hoveredVertical = item.value;
|
5036 | this.deactivateAll();
|
5037 | }
|
5038 | hideCircles() {
|
5039 | this.hoveredVertical = null;
|
5040 | this.deactivateAll();
|
5041 | }
|
5042 | onClick(data, series) {
|
5043 | if (series) {
|
5044 | data.series = series.name;
|
5045 | }
|
5046 | this.select.emit(data);
|
5047 | }
|
5048 | trackBy(index, item) {
|
5049 | return `${item.name}`;
|
5050 | }
|
5051 | setColors() {
|
5052 | let domain;
|
5053 | if (this.schemeType === ScaleType.Ordinal) {
|
5054 | domain = this.seriesDomain;
|
5055 | }
|
5056 | else {
|
5057 | domain = this.yDomain;
|
5058 | }
|
5059 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
5060 | }
|
5061 | getLegendOptions() {
|
5062 | const opts = {
|
5063 | scaleType: this.schemeType,
|
5064 | colors: undefined,
|
5065 | domain: [],
|
5066 | title: undefined,
|
5067 | position: this.legendPosition
|
5068 | };
|
5069 | if (opts.scaleType === ScaleType.Ordinal) {
|
5070 | opts.domain = this.seriesDomain;
|
5071 | opts.colors = this.colors;
|
5072 | opts.title = this.legendTitle;
|
5073 | }
|
5074 | else {
|
5075 | opts.domain = this.yDomain;
|
5076 | opts.colors = this.colors.scale;
|
5077 | }
|
5078 | return opts;
|
5079 | }
|
5080 | updateYAxisWidth({ width }) {
|
5081 | this.yAxisWidth = width;
|
5082 | this.update();
|
5083 | }
|
5084 | updateXAxisHeight({ height }) {
|
5085 | this.xAxisHeight = height;
|
5086 | this.update();
|
5087 | }
|
5088 | onActivate(item) {
|
5089 | const idx = this.activeEntries.findIndex(d => {
|
5090 | return d.name === item.name && d.value === item.value;
|
5091 | });
|
5092 | if (idx > -1) {
|
5093 | return;
|
5094 | }
|
5095 | this.activeEntries = [item, ...this.activeEntries];
|
5096 | this.activate.emit({ value: item, entries: this.activeEntries });
|
5097 | }
|
5098 | onDeactivate(item) {
|
5099 | const idx = this.activeEntries.findIndex(d => {
|
5100 | return d.name === item.name && d.value === item.value;
|
5101 | });
|
5102 | this.activeEntries.splice(idx, 1);
|
5103 | this.activeEntries = [...this.activeEntries];
|
5104 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
5105 | }
|
5106 | deactivateAll() {
|
5107 | this.activeEntries = [...this.activeEntries];
|
5108 | for (const entry of this.activeEntries) {
|
5109 | this.deactivate.emit({ value: entry, entries: [] });
|
5110 | }
|
5111 | this.activeEntries = [];
|
5112 | }
|
5113 | }
|
5114 | AreaChartStackedComponent.decorators = [
|
5115 | { type: Component, args: [{
|
5116 | selector: 'ngx-charts-area-chart-stacked',
|
5117 | template: `
|
5118 | <ngx-charts-chart
|
5119 | [view]="[width, height]"
|
5120 | [showLegend]="legend"
|
5121 | [legendOptions]="legendOptions"
|
5122 | [activeEntries]="activeEntries"
|
5123 | [animations]="animations"
|
5124 | (legendLabelClick)="onClick($event)"
|
5125 | (legendLabelActivate)="onActivate($event)"
|
5126 | (legendLabelDeactivate)="onDeactivate($event)"
|
5127 | >
|
5128 | <svg:defs>
|
5129 | <svg:clipPath [attr.id]="clipPathId">
|
5130 | <svg:rect
|
5131 | [attr.width]="dims.width + 10"
|
5132 | [attr.height]="dims.height + 10"
|
5133 | [attr.transform]="'translate(-5, -5)'"
|
5134 | />
|
5135 | </svg:clipPath>
|
5136 | </svg:defs>
|
5137 | <svg:g [attr.transform]="transform" class="area-chart chart">
|
5138 | <svg:g
|
5139 | ngx-charts-x-axis
|
5140 | *ngIf="xAxis"
|
5141 | [xScale]="xScale"
|
5142 | [dims]="dims"
|
5143 | [showGridLines]="showGridLines"
|
5144 | [showLabel]="showXAxisLabel"
|
5145 | [labelText]="xAxisLabel"
|
5146 | [trimTicks]="trimXAxisTicks"
|
5147 | [rotateTicks]="rotateXAxisTicks"
|
5148 | [maxTickLength]="maxXAxisTickLength"
|
5149 | [tickFormatting]="xAxisTickFormatting"
|
5150 | [ticks]="xAxisTicks"
|
5151 | (dimensionsChanged)="updateXAxisHeight($event)"
|
5152 | ></svg:g>
|
5153 | <svg:g
|
5154 | ngx-charts-y-axis
|
5155 | *ngIf="yAxis"
|
5156 | [yScale]="yScale"
|
5157 | [dims]="dims"
|
5158 | [showGridLines]="showGridLines"
|
5159 | [showLabel]="showYAxisLabel"
|
5160 | [labelText]="yAxisLabel"
|
5161 | [trimTicks]="trimYAxisTicks"
|
5162 | [maxTickLength]="maxYAxisTickLength"
|
5163 | [tickFormatting]="yAxisTickFormatting"
|
5164 | [ticks]="yAxisTicks"
|
5165 | (dimensionsChanged)="updateYAxisWidth($event)"
|
5166 | ></svg:g>
|
5167 | <svg:g [attr.clip-path]="clipPath">
|
5168 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
5169 | <svg:g
|
5170 | ngx-charts-area-series
|
5171 | [xScale]="xScale"
|
5172 | [yScale]="yScale"
|
5173 | [colors]="colors"
|
5174 | [data]="series"
|
5175 | [scaleType]="scaleType"
|
5176 | [gradient]="gradient"
|
5177 | [activeEntries]="activeEntries"
|
5178 | [stacked]="true"
|
5179 | [curve]="curve"
|
5180 | [animations]="animations"
|
5181 | />
|
5182 | </svg:g>
|
5183 |
|
5184 | <svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
5185 | <svg:g
|
5186 | ngx-charts-tooltip-area
|
5187 | [dims]="dims"
|
5188 | [xSet]="xSet"
|
5189 | [xScale]="xScale"
|
5190 | [yScale]="yScale"
|
5191 | [results]="results"
|
5192 | [colors]="colors"
|
5193 | [tooltipDisabled]="tooltipDisabled"
|
5194 | [tooltipTemplate]="seriesTooltipTemplate"
|
5195 | (hover)="updateHoveredVertical($event)"
|
5196 | />
|
5197 |
|
5198 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
5199 | <svg:g
|
5200 | ngx-charts-circle-series
|
5201 | [type]="seriesType.Stacked"
|
5202 | [xScale]="xScale"
|
5203 | [yScale]="yScale"
|
5204 | [colors]="colors"
|
5205 | [activeEntries]="activeEntries"
|
5206 | [data]="series"
|
5207 | [scaleType]="scaleType"
|
5208 | [visibleValue]="hoveredVertical"
|
5209 | [tooltipDisabled]="tooltipDisabled"
|
5210 | [tooltipTemplate]="tooltipTemplate"
|
5211 | (select)="onClick($event, series)"
|
5212 | (activate)="onActivate($event)"
|
5213 | (deactivate)="onDeactivate($event)"
|
5214 | />
|
5215 | </svg:g>
|
5216 | </svg:g>
|
5217 | </svg:g>
|
5218 | </svg:g>
|
5219 | <svg:g
|
5220 | ngx-charts-timeline
|
5221 | *ngIf="timeline && scaleType != 'ordinal'"
|
5222 | [attr.transform]="timelineTransform"
|
5223 | [results]="results"
|
5224 | [view]="[timelineWidth, height]"
|
5225 | [height]="timelineHeight"
|
5226 | [scheme]="scheme"
|
5227 | [customColors]="customColors"
|
5228 | [legend]="legend"
|
5229 | [scaleType]="scaleType"
|
5230 | (onDomainChange)="updateDomain($event)"
|
5231 | >
|
5232 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
5233 | <svg:g
|
5234 | ngx-charts-area-series
|
5235 | [xScale]="timelineXScale"
|
5236 | [yScale]="timelineYScale"
|
5237 | [colors]="colors"
|
5238 | [data]="series"
|
5239 | [scaleType]="scaleType"
|
5240 | [gradient]="gradient"
|
5241 | [stacked]="true"
|
5242 | [curve]="curve"
|
5243 | [animations]="animations"
|
5244 | />
|
5245 | </svg:g>
|
5246 | </svg:g>
|
5247 | </ngx-charts-chart>
|
5248 | `,
|
5249 | changeDetection: ChangeDetectionStrategy.OnPush,
|
5250 | encapsulation: ViewEncapsulation.None,
|
5251 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
5252 | },] }
|
5253 | ];
|
5254 | AreaChartStackedComponent.propDecorators = {
|
5255 | legend: [{ type: Input }],
|
5256 | legendTitle: [{ type: Input }],
|
5257 | legendPosition: [{ type: Input }],
|
5258 | xAxis: [{ type: Input }],
|
5259 | yAxis: [{ type: Input }],
|
5260 | showXAxisLabel: [{ type: Input }],
|
5261 | showYAxisLabel: [{ type: Input }],
|
5262 | xAxisLabel: [{ type: Input }],
|
5263 | yAxisLabel: [{ type: Input }],
|
5264 | timeline: [{ type: Input }],
|
5265 | gradient: [{ type: Input }],
|
5266 | showGridLines: [{ type: Input }],
|
5267 | curve: [{ type: Input }],
|
5268 | activeEntries: [{ type: Input }],
|
5269 | schemeType: [{ type: Input }],
|
5270 | trimXAxisTicks: [{ type: Input }],
|
5271 | trimYAxisTicks: [{ type: Input }],
|
5272 | rotateXAxisTicks: [{ type: Input }],
|
5273 | maxXAxisTickLength: [{ type: Input }],
|
5274 | maxYAxisTickLength: [{ type: Input }],
|
5275 | xAxisTickFormatting: [{ type: Input }],
|
5276 | yAxisTickFormatting: [{ type: Input }],
|
5277 | xAxisTicks: [{ type: Input }],
|
5278 | yAxisTicks: [{ type: Input }],
|
5279 | roundDomains: [{ type: Input }],
|
5280 | tooltipDisabled: [{ type: Input }],
|
5281 | xScaleMin: [{ type: Input }],
|
5282 | xScaleMax: [{ type: Input }],
|
5283 | yScaleMin: [{ type: Input }],
|
5284 | yScaleMax: [{ type: Input }],
|
5285 | activate: [{ type: Output }],
|
5286 | deactivate: [{ type: Output }],
|
5287 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
5288 | seriesTooltipTemplate: [{ type: ContentChild, args: ['seriesTooltipTemplate',] }],
|
5289 | hideCircles: [{ type: HostListener, args: ['mouseleave',] }]
|
5290 | };
|
5291 |
|
5292 | function sortLinear(data, property, direction = 'asc') {
|
5293 | return data.sort((a, b) => {
|
5294 | if (direction === 'asc') {
|
5295 | return a[property] - b[property];
|
5296 | }
|
5297 | else {
|
5298 | return b[property] - a[property];
|
5299 | }
|
5300 | });
|
5301 | }
|
5302 | function sortByDomain(data, property, direction = 'asc', domain) {
|
5303 | return data.sort((a, b) => {
|
5304 | const aVal = a[property];
|
5305 | const bVal = b[property];
|
5306 | const aIdx = domain.indexOf(aVal);
|
5307 | const bIdx = domain.indexOf(bVal);
|
5308 | if (direction === 'asc') {
|
5309 | return aIdx - bIdx;
|
5310 | }
|
5311 | else {
|
5312 | return bIdx - aIdx;
|
5313 | }
|
5314 | });
|
5315 | }
|
5316 | function sortByTime(data, property, direction = 'asc') {
|
5317 | return data.sort((a, b) => {
|
5318 | const aDate = a[property].getTime();
|
5319 | const bDate = b[property].getTime();
|
5320 | if (direction === 'asc') {
|
5321 | if (aDate > bDate)
|
5322 | return 1;
|
5323 | if (bDate > aDate)
|
5324 | return -1;
|
5325 | return 0;
|
5326 | }
|
5327 | else {
|
5328 | if (aDate > bDate)
|
5329 | return -1;
|
5330 | if (bDate > aDate)
|
5331 | return 1;
|
5332 | return 0;
|
5333 | }
|
5334 | });
|
5335 | }
|
5336 |
|
5337 | class AreaSeriesComponent {
|
5338 | constructor() {
|
5339 | this.baseValue = 'auto';
|
5340 | this.stacked = false;
|
5341 | this.normalized = false;
|
5342 | this.animations = true;
|
5343 | this.select = new EventEmitter();
|
5344 | }
|
5345 | ngOnChanges(changes) {
|
5346 | this.update();
|
5347 | }
|
5348 | update() {
|
5349 | this.updateGradient();
|
5350 | let currentArea;
|
5351 | let startingArea;
|
5352 | const xProperty = d => {
|
5353 | const label = d.name;
|
5354 | return this.xScale(label);
|
5355 | };
|
5356 | if (this.stacked || this.normalized) {
|
5357 | currentArea = area()
|
5358 | .x(xProperty)
|
5359 | .y0((d, i) => this.yScale(d.d0))
|
5360 | .y1((d, i) => this.yScale(d.d1));
|
5361 | startingArea = area()
|
5362 | .x(xProperty)
|
5363 | .y0(d => this.yScale.range()[0])
|
5364 | .y1(d => this.yScale.range()[0]);
|
5365 | }
|
5366 | else {
|
5367 | currentArea = area()
|
5368 | .x(xProperty)
|
5369 | .y0(() => (this.baseValue === 'auto' ? this.yScale.range()[0] : this.yScale(this.baseValue)))
|
5370 | .y1(d => this.yScale(d.value));
|
5371 | startingArea = area()
|
5372 | .x(xProperty)
|
5373 | .y0(d => (this.baseValue === 'auto' ? this.yScale.range()[0] : this.yScale(this.baseValue)))
|
5374 | .y1(d => (this.baseValue === 'auto' ? this.yScale.range()[0] : this.yScale(this.baseValue)));
|
5375 | }
|
5376 | currentArea.curve(this.curve);
|
5377 | startingArea.curve(this.curve);
|
5378 | this.opacity = 0.8;
|
5379 | let data = this.data.series;
|
5380 | if (this.scaleType === ScaleType.Linear) {
|
5381 | data = sortLinear(data, 'name');
|
5382 | }
|
5383 | else if (this.scaleType === ScaleType.Time) {
|
5384 | data = sortByTime(data, 'name');
|
5385 | }
|
5386 | else {
|
5387 | data = sortByDomain(data, 'name', 'asc', this.xScale.domain());
|
5388 | }
|
5389 | this.path = currentArea(data);
|
5390 | this.startingPath = startingArea(data);
|
5391 | }
|
5392 | updateGradient() {
|
5393 | if (this.colors.scaleType === ScaleType.Linear) {
|
5394 | this.hasGradient = true;
|
5395 | if (this.stacked || this.normalized) {
|
5396 | const d0values = this.data.series.map(d => d.d0);
|
5397 | const d1values = this.data.series.map(d => d.d1);
|
5398 | const max = Math.max(...d1values);
|
5399 | const min = Math.min(...d0values);
|
5400 | this.gradientStops = this.colors.getLinearGradientStops(max, min);
|
5401 | }
|
5402 | else {
|
5403 | const values = this.data.series.map(d => d.value);
|
5404 | const max = Math.max(...values);
|
5405 | this.gradientStops = this.colors.getLinearGradientStops(max);
|
5406 | }
|
5407 | }
|
5408 | else {
|
5409 | this.hasGradient = false;
|
5410 | this.gradientStops = undefined;
|
5411 | }
|
5412 | }
|
5413 | isActive(entry) {
|
5414 | if (!this.activeEntries)
|
5415 | return false;
|
5416 | const item = this.activeEntries.find(d => {
|
5417 | return entry.name === d.name;
|
5418 | });
|
5419 | return item !== undefined;
|
5420 | }
|
5421 | isInactive(entry) {
|
5422 | if (!this.activeEntries || this.activeEntries.length === 0)
|
5423 | return false;
|
5424 | const item = this.activeEntries.find(d => {
|
5425 | return entry.name === d.name;
|
5426 | });
|
5427 | return item === undefined;
|
5428 | }
|
5429 | }
|
5430 | AreaSeriesComponent.decorators = [
|
5431 | { type: Component, args: [{
|
5432 | selector: 'g[ngx-charts-area-series]',
|
5433 | template: `
|
5434 | <svg:g
|
5435 | ngx-charts-area
|
5436 | class="area-series"
|
5437 | [data]="data"
|
5438 | [path]="path"
|
5439 | [fill]="colors.getColor(data.name)"
|
5440 | [stops]="gradientStops"
|
5441 | [startingPath]="startingPath"
|
5442 | [opacity]="opacity"
|
5443 | [gradient]="gradient || hasGradient"
|
5444 | [animations]="animations"
|
5445 | [class.active]="isActive(data)"
|
5446 | [class.inactive]="isInactive(data)"
|
5447 | />
|
5448 | `,
|
5449 | changeDetection: ChangeDetectionStrategy.OnPush
|
5450 | },] }
|
5451 | ];
|
5452 | AreaSeriesComponent.propDecorators = {
|
5453 | data: [{ type: Input }],
|
5454 | xScale: [{ type: Input }],
|
5455 | yScale: [{ type: Input }],
|
5456 | baseValue: [{ type: Input }],
|
5457 | colors: [{ type: Input }],
|
5458 | scaleType: [{ type: Input }],
|
5459 | stacked: [{ type: Input }],
|
5460 | normalized: [{ type: Input }],
|
5461 | gradient: [{ type: Input }],
|
5462 | curve: [{ type: Input }],
|
5463 | activeEntries: [{ type: Input }],
|
5464 | animations: [{ type: Input }],
|
5465 | select: [{ type: Output }]
|
5466 | };
|
5467 |
|
5468 | class AreaChartModule {
|
5469 | }
|
5470 | AreaChartModule.decorators = [
|
5471 | { type: NgModule, args: [{
|
5472 | imports: [ChartCommonModule],
|
5473 | declarations: [AreaChartComponent, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaSeriesComponent],
|
5474 | exports: [AreaChartComponent, AreaChartNormalizedComponent, AreaChartStackedComponent, AreaSeriesComponent]
|
5475 | },] }
|
5476 | ];
|
5477 |
|
5478 | class BarComponent {
|
5479 | constructor(element) {
|
5480 | this.roundEdges = true;
|
5481 | this.gradient = false;
|
5482 | this.offset = 0;
|
5483 | this.isActive = false;
|
5484 | this.animations = true;
|
5485 | this.noBarWhenZero = true;
|
5486 | this.select = new EventEmitter();
|
5487 | this.activate = new EventEmitter();
|
5488 | this.deactivate = new EventEmitter();
|
5489 | this.hasGradient = false;
|
5490 | this.hideBar = false;
|
5491 | this.element = element.nativeElement;
|
5492 | }
|
5493 | ngOnChanges(changes) {
|
5494 | if (changes.roundEdges) {
|
5495 | this.loadAnimation();
|
5496 | }
|
5497 | this.update();
|
5498 | }
|
5499 | update() {
|
5500 | this.gradientId = 'grad' + id().toString();
|
5501 | this.gradientFill = `url(#${this.gradientId})`;
|
5502 | if (this.gradient || this.stops) {
|
5503 | this.gradientStops = this.getGradient();
|
5504 | this.hasGradient = true;
|
5505 | }
|
5506 | else {
|
5507 | this.hasGradient = false;
|
5508 | }
|
5509 | this.updatePathEl();
|
5510 | this.checkToHideBar();
|
5511 | }
|
5512 | loadAnimation() {
|
5513 | this.path = this.getStartingPath();
|
5514 | setTimeout(this.update.bind(this), 100);
|
5515 | }
|
5516 | updatePathEl() {
|
5517 | const node = select(this.element).select('.bar');
|
5518 | const path = this.getPath();
|
5519 | if (this.animations) {
|
5520 | node.transition().duration(500).attr('d', path);
|
5521 | }
|
5522 | else {
|
5523 | node.attr('d', path);
|
5524 | }
|
5525 | }
|
5526 | getGradient() {
|
5527 | if (this.stops) {
|
5528 | return this.stops;
|
5529 | }
|
5530 | return [
|
5531 | {
|
5532 | offset: 0,
|
5533 | color: this.fill,
|
5534 | opacity: this.getStartOpacity()
|
5535 | },
|
5536 | {
|
5537 | offset: 100,
|
5538 | color: this.fill,
|
5539 | opacity: 1
|
5540 | }
|
5541 | ];
|
5542 | }
|
5543 | getStartingPath() {
|
5544 | if (!this.animations) {
|
5545 | return this.getPath();
|
5546 | }
|
5547 | let radius = this.getRadius();
|
5548 | let path;
|
5549 | if (this.roundEdges) {
|
5550 | if (this.orientation === BarOrientation.Vertical) {
|
5551 | radius = Math.min(this.height, radius);
|
5552 | path = roundedRect(this.x, this.y + this.height, this.width, 1, 0, this.edges);
|
5553 | }
|
5554 | else if (this.orientation === BarOrientation.Horizontal) {
|
5555 | radius = Math.min(this.width, radius);
|
5556 | path = roundedRect(this.x, this.y, 1, this.height, 0, this.edges);
|
5557 | }
|
5558 | }
|
5559 | else {
|
5560 | if (this.orientation === BarOrientation.Vertical) {
|
5561 | path = roundedRect(this.x, this.y + this.height, this.width, 1, 0, this.edges);
|
5562 | }
|
5563 | else if (this.orientation === BarOrientation.Horizontal) {
|
5564 | path = roundedRect(this.x, this.y, 1, this.height, 0, this.edges);
|
5565 | }
|
5566 | }
|
5567 | return path;
|
5568 | }
|
5569 | getPath() {
|
5570 | let radius = this.getRadius();
|
5571 | let path;
|
5572 | if (this.roundEdges) {
|
5573 | if (this.orientation === BarOrientation.Vertical) {
|
5574 | radius = Math.min(this.height, radius);
|
5575 | path = roundedRect(this.x, this.y, this.width, this.height, radius, this.edges);
|
5576 | }
|
5577 | else if (this.orientation === BarOrientation.Horizontal) {
|
5578 | radius = Math.min(this.width, radius);
|
5579 | path = roundedRect(this.x, this.y, this.width, this.height, radius, this.edges);
|
5580 | }
|
5581 | }
|
5582 | else {
|
5583 | path = roundedRect(this.x, this.y, this.width, this.height, radius, this.edges);
|
5584 | }
|
5585 | return path;
|
5586 | }
|
5587 | getRadius() {
|
5588 | let radius = 0;
|
5589 | if (this.roundEdges && this.height > 5 && this.width > 5) {
|
5590 | radius = Math.floor(Math.min(5, this.height / 2, this.width / 2));
|
5591 | }
|
5592 | return radius;
|
5593 | }
|
5594 | getStartOpacity() {
|
5595 | if (this.roundEdges) {
|
5596 | return 0.2;
|
5597 | }
|
5598 | else {
|
5599 | return 0.5;
|
5600 | }
|
5601 | }
|
5602 | get edges() {
|
5603 | let edges = [false, false, false, false];
|
5604 | if (this.roundEdges) {
|
5605 | if (this.orientation === BarOrientation.Vertical) {
|
5606 | if (this.data.value > 0) {
|
5607 | edges = [true, true, false, false];
|
5608 | }
|
5609 | else {
|
5610 | edges = [false, false, true, true];
|
5611 | }
|
5612 | }
|
5613 | else if (this.orientation === BarOrientation.Horizontal) {
|
5614 | if (this.data.value > 0) {
|
5615 | edges = [false, true, false, true];
|
5616 | }
|
5617 | else {
|
5618 | edges = [true, false, true, false];
|
5619 | }
|
5620 | }
|
5621 | }
|
5622 | return edges;
|
5623 | }
|
5624 | onMouseEnter() {
|
5625 | this.activate.emit(this.data);
|
5626 | }
|
5627 | onMouseLeave() {
|
5628 | this.deactivate.emit(this.data);
|
5629 | }
|
5630 | checkToHideBar() {
|
5631 | this.hideBar =
|
5632 | this.noBarWhenZero &&
|
5633 | ((this.orientation === BarOrientation.Vertical && this.height === 0) ||
|
5634 | (this.orientation === BarOrientation.Horizontal && this.width === 0));
|
5635 | }
|
5636 | }
|
5637 | BarComponent.decorators = [
|
5638 | { type: Component, args: [{
|
5639 | selector: 'g[ngx-charts-bar]',
|
5640 | template: `
|
5641 | <svg:defs *ngIf="hasGradient">
|
5642 | <svg:g ngx-charts-svg-linear-gradient [orientation]="orientation" [name]="gradientId" [stops]="gradientStops" />
|
5643 | </svg:defs>
|
5644 | <svg:path
|
5645 | class="bar"
|
5646 | stroke="none"
|
5647 | role="img"
|
5648 | tabIndex="-1"
|
5649 | [class.active]="isActive"
|
5650 | [class.hidden]="hideBar"
|
5651 | [attr.d]="path"
|
5652 | [attr.aria-label]="ariaLabel"
|
5653 | [attr.fill]="hasGradient ? gradientFill : fill"
|
5654 | (click)="select.emit(data)"
|
5655 | />
|
5656 | `,
|
5657 | changeDetection: ChangeDetectionStrategy.OnPush
|
5658 | },] }
|
5659 | ];
|
5660 | BarComponent.ctorParameters = () => [
|
5661 | { type: ElementRef }
|
5662 | ];
|
5663 | BarComponent.propDecorators = {
|
5664 | fill: [{ type: Input }],
|
5665 | data: [{ type: Input }],
|
5666 | width: [{ type: Input }],
|
5667 | height: [{ type: Input }],
|
5668 | x: [{ type: Input }],
|
5669 | y: [{ type: Input }],
|
5670 | orientation: [{ type: Input }],
|
5671 | roundEdges: [{ type: Input }],
|
5672 | gradient: [{ type: Input }],
|
5673 | offset: [{ type: Input }],
|
5674 | isActive: [{ type: Input }],
|
5675 | stops: [{ type: Input }],
|
5676 | animations: [{ type: Input }],
|
5677 | ariaLabel: [{ type: Input }],
|
5678 | noBarWhenZero: [{ type: Input }],
|
5679 | select: [{ type: Output }],
|
5680 | activate: [{ type: Output }],
|
5681 | deactivate: [{ type: Output }],
|
5682 | onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
5683 | onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
|
5684 | };
|
5685 |
|
5686 | class BarHorizontalComponent extends BaseChartComponent {
|
5687 | constructor() {
|
5688 | super(...arguments);
|
5689 | this.legend = false;
|
5690 | this.legendTitle = 'Legend';
|
5691 | this.legendPosition = LegendPosition.Right;
|
5692 | this.tooltipDisabled = false;
|
5693 | this.showGridLines = true;
|
5694 | this.activeEntries = [];
|
5695 | this.trimXAxisTicks = true;
|
5696 | this.trimYAxisTicks = true;
|
5697 | this.rotateXAxisTicks = true;
|
5698 | this.maxXAxisTickLength = 16;
|
5699 | this.maxYAxisTickLength = 16;
|
5700 | this.barPadding = 8;
|
5701 | this.roundDomains = false;
|
5702 | this.roundEdges = true;
|
5703 | this.showDataLabel = false;
|
5704 | this.noBarWhenZero = true;
|
5705 | this.activate = new EventEmitter();
|
5706 | this.deactivate = new EventEmitter();
|
5707 | this.margin = [10, 20, 10, 20];
|
5708 | this.xAxisHeight = 0;
|
5709 | this.yAxisWidth = 0;
|
5710 | this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
5711 | }
|
5712 | update() {
|
5713 | super.update();
|
5714 | if (!this.showDataLabel) {
|
5715 | this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
5716 | }
|
5717 | this.margin = [10, 20 + this.dataLabelMaxWidth.positive, 10, 20 + this.dataLabelMaxWidth.negative];
|
5718 | this.dims = calculateViewDimensions({
|
5719 | width: this.width,
|
5720 | height: this.height,
|
5721 | margins: this.margin,
|
5722 | showXAxis: this.xAxis,
|
5723 | showYAxis: this.yAxis,
|
5724 | xAxisHeight: this.xAxisHeight,
|
5725 | yAxisWidth: this.yAxisWidth,
|
5726 | showXLabel: this.showXAxisLabel,
|
5727 | showYLabel: this.showYAxisLabel,
|
5728 | showLegend: this.legend,
|
5729 | legendType: this.schemeType,
|
5730 | legendPosition: this.legendPosition
|
5731 | });
|
5732 | this.formatDates();
|
5733 | this.xScale = this.getXScale();
|
5734 | this.yScale = this.getYScale();
|
5735 | this.setColors();
|
5736 | this.legendOptions = this.getLegendOptions();
|
5737 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
5738 | }
|
5739 | getXScale() {
|
5740 | this.xDomain = this.getXDomain();
|
5741 | const scale = scaleLinear().range([0, this.dims.width]).domain(this.xDomain);
|
5742 | return this.roundDomains ? scale.nice() : scale;
|
5743 | }
|
5744 | getYScale() {
|
5745 | this.yDomain = this.getYDomain();
|
5746 | const spacing = this.yDomain.length / (this.dims.height / this.barPadding + 1);
|
5747 | return scaleBand().rangeRound([0, this.dims.height]).paddingInner(spacing).domain(this.yDomain);
|
5748 | }
|
5749 | getXDomain() {
|
5750 | const values = this.results.map(d => d.value);
|
5751 | const min = this.xScaleMin ? Math.min(this.xScaleMin, ...values) : Math.min(0, ...values);
|
5752 | const max = this.xScaleMax ? Math.max(this.xScaleMax, ...values) : Math.max(0, ...values);
|
5753 | return [min, max];
|
5754 | }
|
5755 | getYDomain() {
|
5756 | return this.results.map(d => d.label);
|
5757 | }
|
5758 | onClick(data) {
|
5759 | this.select.emit(data);
|
5760 | }
|
5761 | setColors() {
|
5762 | let domain;
|
5763 | if (this.schemeType === ScaleType.Ordinal) {
|
5764 | domain = this.yDomain;
|
5765 | }
|
5766 | else {
|
5767 | domain = this.xDomain;
|
5768 | }
|
5769 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
5770 | }
|
5771 | getLegendOptions() {
|
5772 | const opts = {
|
5773 | scaleType: this.schemeType,
|
5774 | colors: undefined,
|
5775 | domain: [],
|
5776 | title: undefined,
|
5777 | position: this.legendPosition
|
5778 | };
|
5779 | if (opts.scaleType === 'ordinal') {
|
5780 | opts.domain = this.yDomain;
|
5781 | opts.colors = this.colors;
|
5782 | opts.title = this.legendTitle;
|
5783 | }
|
5784 | else {
|
5785 | opts.domain = this.xDomain;
|
5786 | opts.colors = this.colors.scale;
|
5787 | }
|
5788 | return opts;
|
5789 | }
|
5790 | updateYAxisWidth({ width }) {
|
5791 | this.yAxisWidth = width;
|
5792 | this.update();
|
5793 | }
|
5794 | updateXAxisHeight({ height }) {
|
5795 | this.xAxisHeight = height;
|
5796 | this.update();
|
5797 | }
|
5798 | onDataLabelMaxWidthChanged(event) {
|
5799 | if (event.size.negative) {
|
5800 | this.dataLabelMaxWidth.negative = Math.max(this.dataLabelMaxWidth.negative, event.size.width);
|
5801 | }
|
5802 | else {
|
5803 | this.dataLabelMaxWidth.positive = Math.max(this.dataLabelMaxWidth.positive, event.size.width);
|
5804 | }
|
5805 | if (event.index === this.results.length - 1) {
|
5806 | setTimeout(() => this.update());
|
5807 | }
|
5808 | }
|
5809 | onActivate(item, fromLegend = false) {
|
5810 | item = this.results.find(d => {
|
5811 | if (fromLegend) {
|
5812 | return d.label === item.name;
|
5813 | }
|
5814 | else {
|
5815 | return d.name === item.name;
|
5816 | }
|
5817 | });
|
5818 | const idx = this.activeEntries.findIndex(d => {
|
5819 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
5820 | });
|
5821 | if (idx > -1) {
|
5822 | return;
|
5823 | }
|
5824 | this.activeEntries = [item, ...this.activeEntries];
|
5825 | this.activate.emit({ value: item, entries: this.activeEntries });
|
5826 | }
|
5827 | onDeactivate(item, fromLegend = false) {
|
5828 | item = this.results.find(d => {
|
5829 | if (fromLegend) {
|
5830 | return d.label === item.name;
|
5831 | }
|
5832 | else {
|
5833 | return d.name === item.name;
|
5834 | }
|
5835 | });
|
5836 | const idx = this.activeEntries.findIndex(d => {
|
5837 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
5838 | });
|
5839 | this.activeEntries.splice(idx, 1);
|
5840 | this.activeEntries = [...this.activeEntries];
|
5841 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
5842 | }
|
5843 | }
|
5844 | BarHorizontalComponent.decorators = [
|
5845 | { type: Component, args: [{
|
5846 | selector: 'ngx-charts-bar-horizontal',
|
5847 | template: `
|
5848 | <ngx-charts-chart
|
5849 | [view]="[width, height]"
|
5850 | [showLegend]="legend"
|
5851 | [legendOptions]="legendOptions"
|
5852 | [activeEntries]="activeEntries"
|
5853 | [animations]="animations"
|
5854 | (legendLabelClick)="onClick($event)"
|
5855 | (legendLabelActivate)="onActivate($event, true)"
|
5856 | (legendLabelDeactivate)="onDeactivate($event, true)"
|
5857 | >
|
5858 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
5859 | <svg:g
|
5860 | ngx-charts-x-axis
|
5861 | *ngIf="xAxis"
|
5862 | [xScale]="xScale"
|
5863 | [dims]="dims"
|
5864 | [showGridLines]="showGridLines"
|
5865 | [showLabel]="showXAxisLabel"
|
5866 | [labelText]="xAxisLabel"
|
5867 | [trimTicks]="trimXAxisTicks"
|
5868 | [rotateTicks]="rotateXAxisTicks"
|
5869 | [maxTickLength]="maxXAxisTickLength"
|
5870 | [tickFormatting]="xAxisTickFormatting"
|
5871 | [ticks]="xAxisTicks"
|
5872 | (dimensionsChanged)="updateXAxisHeight($event)"
|
5873 | ></svg:g>
|
5874 | <svg:g
|
5875 | ngx-charts-y-axis
|
5876 | *ngIf="yAxis"
|
5877 | [yScale]="yScale"
|
5878 | [dims]="dims"
|
5879 | [showLabel]="showYAxisLabel"
|
5880 | [labelText]="yAxisLabel"
|
5881 | [trimTicks]="trimYAxisTicks"
|
5882 | [maxTickLength]="maxYAxisTickLength"
|
5883 | [tickFormatting]="yAxisTickFormatting"
|
5884 | [ticks]="yAxisTicks"
|
5885 | [yAxisOffset]="dataLabelMaxWidth.negative"
|
5886 | (dimensionsChanged)="updateYAxisWidth($event)"
|
5887 | ></svg:g>
|
5888 | <svg:g
|
5889 | ngx-charts-series-horizontal
|
5890 | [xScale]="xScale"
|
5891 | [yScale]="yScale"
|
5892 | [colors]="colors"
|
5893 | [series]="results"
|
5894 | [dims]="dims"
|
5895 | [gradient]="gradient"
|
5896 | [tooltipDisabled]="tooltipDisabled"
|
5897 | [tooltipTemplate]="tooltipTemplate"
|
5898 | [activeEntries]="activeEntries"
|
5899 | [roundEdges]="roundEdges"
|
5900 | [animations]="animations"
|
5901 | [showDataLabel]="showDataLabel"
|
5902 | [dataLabelFormatting]="dataLabelFormatting"
|
5903 | [noBarWhenZero]="noBarWhenZero"
|
5904 | (select)="onClick($event)"
|
5905 | (activate)="onActivate($event)"
|
5906 | (deactivate)="onDeactivate($event)"
|
5907 | (dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event)"
|
5908 | ></svg:g>
|
5909 | </svg:g>
|
5910 | </ngx-charts-chart>
|
5911 | `,
|
5912 | changeDetection: ChangeDetectionStrategy.OnPush,
|
5913 | encapsulation: ViewEncapsulation.None,
|
5914 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
5915 | },] }
|
5916 | ];
|
5917 | BarHorizontalComponent.propDecorators = {
|
5918 | legend: [{ type: Input }],
|
5919 | legendTitle: [{ type: Input }],
|
5920 | legendPosition: [{ type: Input }],
|
5921 | xAxis: [{ type: Input }],
|
5922 | yAxis: [{ type: Input }],
|
5923 | showXAxisLabel: [{ type: Input }],
|
5924 | showYAxisLabel: [{ type: Input }],
|
5925 | xAxisLabel: [{ type: Input }],
|
5926 | yAxisLabel: [{ type: Input }],
|
5927 | tooltipDisabled: [{ type: Input }],
|
5928 | gradient: [{ type: Input }],
|
5929 | showGridLines: [{ type: Input }],
|
5930 | activeEntries: [{ type: Input }],
|
5931 | schemeType: [{ type: Input }],
|
5932 | trimXAxisTicks: [{ type: Input }],
|
5933 | trimYAxisTicks: [{ type: Input }],
|
5934 | rotateXAxisTicks: [{ type: Input }],
|
5935 | maxXAxisTickLength: [{ type: Input }],
|
5936 | maxYAxisTickLength: [{ type: Input }],
|
5937 | xAxisTickFormatting: [{ type: Input }],
|
5938 | yAxisTickFormatting: [{ type: Input }],
|
5939 | xAxisTicks: [{ type: Input }],
|
5940 | yAxisTicks: [{ type: Input }],
|
5941 | barPadding: [{ type: Input }],
|
5942 | roundDomains: [{ type: Input }],
|
5943 | roundEdges: [{ type: Input }],
|
5944 | xScaleMax: [{ type: Input }],
|
5945 | xScaleMin: [{ type: Input }],
|
5946 | showDataLabel: [{ type: Input }],
|
5947 | dataLabelFormatting: [{ type: Input }],
|
5948 | noBarWhenZero: [{ type: Input }],
|
5949 | activate: [{ type: Output }],
|
5950 | deactivate: [{ type: Output }],
|
5951 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
5952 | };
|
5953 |
|
5954 | class BarHorizontal2DComponent extends BaseChartComponent {
|
5955 | constructor() {
|
5956 | super(...arguments);
|
5957 | this.legend = false;
|
5958 | this.legendTitle = 'Legend';
|
5959 | this.legendPosition = LegendPosition.Right;
|
5960 | this.tooltipDisabled = false;
|
5961 | this.showGridLines = true;
|
5962 | this.activeEntries = [];
|
5963 | this.trimXAxisTicks = true;
|
5964 | this.trimYAxisTicks = true;
|
5965 | this.rotateXAxisTicks = true;
|
5966 | this.maxXAxisTickLength = 16;
|
5967 | this.maxYAxisTickLength = 16;
|
5968 | this.groupPadding = 16;
|
5969 | this.barPadding = 8;
|
5970 | this.roundDomains = false;
|
5971 | this.roundEdges = true;
|
5972 | this.showDataLabel = false;
|
5973 | this.noBarWhenZero = true;
|
5974 | this.activate = new EventEmitter();
|
5975 | this.deactivate = new EventEmitter();
|
5976 | this.margin = [10, 20, 10, 20];
|
5977 | this.xAxisHeight = 0;
|
5978 | this.yAxisWidth = 0;
|
5979 | this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
5980 | this.barOrientation = BarOrientation;
|
5981 | this.trackBy = (index, item) => {
|
5982 | return item.name;
|
5983 | };
|
5984 | }
|
5985 | update() {
|
5986 | super.update();
|
5987 | if (!this.showDataLabel) {
|
5988 | this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
5989 | }
|
5990 | this.margin = [10, 20 + this.dataLabelMaxWidth.positive, 10, 20 + this.dataLabelMaxWidth.negative];
|
5991 | this.dims = calculateViewDimensions({
|
5992 | width: this.width,
|
5993 | height: this.height,
|
5994 | margins: this.margin,
|
5995 | showXAxis: this.xAxis,
|
5996 | showYAxis: this.yAxis,
|
5997 | xAxisHeight: this.xAxisHeight,
|
5998 | yAxisWidth: this.yAxisWidth,
|
5999 | showXLabel: this.showXAxisLabel,
|
6000 | showYLabel: this.showYAxisLabel,
|
6001 | showLegend: this.legend,
|
6002 | legendType: this.schemeType,
|
6003 | legendPosition: this.legendPosition
|
6004 | });
|
6005 | this.formatDates();
|
6006 | this.groupDomain = this.getGroupDomain();
|
6007 | this.innerDomain = this.getInnerDomain();
|
6008 | this.valueDomain = this.getValueDomain();
|
6009 | this.groupScale = this.getGroupScale();
|
6010 | this.innerScale = this.getInnerScale();
|
6011 | this.valueScale = this.getValueScale();
|
6012 | this.setColors();
|
6013 | this.legendOptions = this.getLegendOptions();
|
6014 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
6015 | }
|
6016 | getGroupScale() {
|
6017 | const spacing = this.groupDomain.length / (this.dims.height / this.groupPadding + 1);
|
6018 | return scaleBand()
|
6019 | .rangeRound([0, this.dims.height])
|
6020 | .paddingInner(spacing)
|
6021 | .paddingOuter(spacing / 2)
|
6022 | .domain(this.groupDomain);
|
6023 | }
|
6024 | getInnerScale() {
|
6025 | const height = this.groupScale.bandwidth();
|
6026 | const spacing = this.innerDomain.length / (height / this.barPadding + 1);
|
6027 | return scaleBand().rangeRound([0, height]).paddingInner(spacing).domain(this.innerDomain);
|
6028 | }
|
6029 | getValueScale() {
|
6030 | const scale = scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
6031 | return this.roundDomains ? scale.nice() : scale;
|
6032 | }
|
6033 | getGroupDomain() {
|
6034 | const domain = [];
|
6035 | for (const group of this.results) {
|
6036 | if (!domain.includes(group.label)) {
|
6037 | domain.push(group.label);
|
6038 | }
|
6039 | }
|
6040 | return domain;
|
6041 | }
|
6042 | getInnerDomain() {
|
6043 | const domain = [];
|
6044 | for (const group of this.results) {
|
6045 | for (const d of group.series) {
|
6046 | if (!domain.includes(d.label)) {
|
6047 | domain.push(d.label);
|
6048 | }
|
6049 | }
|
6050 | }
|
6051 | return domain;
|
6052 | }
|
6053 | getValueDomain() {
|
6054 | const domain = [];
|
6055 | for (const group of this.results) {
|
6056 | for (const d of group.series) {
|
6057 | if (!domain.includes(d.value)) {
|
6058 | domain.push(d.value);
|
6059 | }
|
6060 | }
|
6061 | }
|
6062 | const min = Math.min(0, ...domain);
|
6063 | const max = this.xScaleMax ? Math.max(this.xScaleMax, ...domain) : Math.max(0, ...domain);
|
6064 | return [min, max];
|
6065 | }
|
6066 | groupTransform(group) {
|
6067 | return `translate(0, ${this.groupScale(group.label)})`;
|
6068 | }
|
6069 | onClick(data, group) {
|
6070 | if (group) {
|
6071 | data.series = group.name;
|
6072 | }
|
6073 | this.select.emit(data);
|
6074 | }
|
6075 | setColors() {
|
6076 | let domain;
|
6077 | if (this.schemeType === ScaleType.Ordinal) {
|
6078 | domain = this.innerDomain;
|
6079 | }
|
6080 | else {
|
6081 | domain = this.valueDomain;
|
6082 | }
|
6083 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
6084 | }
|
6085 | getLegendOptions() {
|
6086 | const opts = {
|
6087 | scaleType: this.schemeType,
|
6088 | colors: undefined,
|
6089 | domain: [],
|
6090 | title: undefined,
|
6091 | position: this.legendPosition
|
6092 | };
|
6093 | if (opts.scaleType === ScaleType.Ordinal) {
|
6094 | opts.domain = this.innerDomain;
|
6095 | opts.colors = this.colors;
|
6096 | opts.title = this.legendTitle;
|
6097 | }
|
6098 | else {
|
6099 | opts.domain = this.valueDomain;
|
6100 | opts.colors = this.colors.scale;
|
6101 | }
|
6102 | return opts;
|
6103 | }
|
6104 | updateYAxisWidth({ width }) {
|
6105 | this.yAxisWidth = width;
|
6106 | this.update();
|
6107 | }
|
6108 | updateXAxisHeight({ height }) {
|
6109 | this.xAxisHeight = height;
|
6110 | this.update();
|
6111 | }
|
6112 | onDataLabelMaxWidthChanged(event, groupIndex) {
|
6113 | if (event.size.negative) {
|
6114 | this.dataLabelMaxWidth.negative = Math.max(this.dataLabelMaxWidth.negative, event.size.width);
|
6115 | }
|
6116 | else {
|
6117 | this.dataLabelMaxWidth.positive = Math.max(this.dataLabelMaxWidth.positive, event.size.width);
|
6118 | }
|
6119 | if (groupIndex === this.results.length - 1) {
|
6120 | setTimeout(() => this.update());
|
6121 | }
|
6122 | }
|
6123 | onActivate(event, group, fromLegend = false) {
|
6124 | const item = Object.assign({}, event);
|
6125 | if (group) {
|
6126 | item.series = group.name;
|
6127 | }
|
6128 | const items = this.results
|
6129 | .map(g => g.series)
|
6130 | .flat()
|
6131 | .filter(i => {
|
6132 | if (fromLegend) {
|
6133 | return i.label === item.name;
|
6134 | }
|
6135 | else {
|
6136 | return i.name === item.name && i.series === item.series;
|
6137 | }
|
6138 | });
|
6139 | this.activeEntries = [...items];
|
6140 | this.activate.emit({ value: item, entries: this.activeEntries });
|
6141 | }
|
6142 | onDeactivate(event, group, fromLegend = false) {
|
6143 | const item = Object.assign({}, event);
|
6144 | if (group) {
|
6145 | item.series = group.name;
|
6146 | }
|
6147 | this.activeEntries = this.activeEntries.filter(i => {
|
6148 | if (fromLegend) {
|
6149 | return i.label !== item.name;
|
6150 | }
|
6151 | else {
|
6152 | return !(i.name === item.name && i.series === item.series);
|
6153 | }
|
6154 | });
|
6155 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
6156 | }
|
6157 | }
|
6158 | BarHorizontal2DComponent.decorators = [
|
6159 | { type: Component, args: [{
|
6160 | selector: 'ngx-charts-bar-horizontal-2d',
|
6161 | template: `
|
6162 | <ngx-charts-chart
|
6163 | [view]="[width, height]"
|
6164 | [showLegend]="legend"
|
6165 | [legendOptions]="legendOptions"
|
6166 | [activeEntries]="activeEntries"
|
6167 | [animations]="animations"
|
6168 | (legendLabelActivate)="onActivate($event, undefined, true)"
|
6169 | (legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
6170 | (legendLabelClick)="onClick($event)"
|
6171 | >
|
6172 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
6173 | <svg:g
|
6174 | ngx-charts-grid-panel-series
|
6175 | [xScale]="valueScale"
|
6176 | [yScale]="groupScale"
|
6177 | [data]="results"
|
6178 | [dims]="dims"
|
6179 | [orient]="barOrientation.Horizontal"
|
6180 | ></svg:g>
|
6181 | <svg:g
|
6182 | ngx-charts-x-axis
|
6183 | *ngIf="xAxis"
|
6184 | [xScale]="valueScale"
|
6185 | [dims]="dims"
|
6186 | [showGridLines]="showGridLines"
|
6187 | [showLabel]="showXAxisLabel"
|
6188 | [labelText]="xAxisLabel"
|
6189 | [trimTicks]="trimXAxisTicks"
|
6190 | [rotateTicks]="rotateXAxisTicks"
|
6191 | [maxTickLength]="maxXAxisTickLength"
|
6192 | [tickFormatting]="xAxisTickFormatting"
|
6193 | [ticks]="xAxisTicks"
|
6194 | (dimensionsChanged)="updateXAxisHeight($event)"
|
6195 | ></svg:g>
|
6196 | <svg:g
|
6197 | ngx-charts-y-axis
|
6198 | *ngIf="yAxis"
|
6199 | [yScale]="groupScale"
|
6200 | [dims]="dims"
|
6201 | [showLabel]="showYAxisLabel"
|
6202 | [labelText]="yAxisLabel"
|
6203 | [trimTicks]="trimYAxisTicks"
|
6204 | [maxTickLength]="maxYAxisTickLength"
|
6205 | [tickFormatting]="yAxisTickFormatting"
|
6206 | [ticks]="yAxisTicks"
|
6207 | [yAxisOffset]="dataLabelMaxWidth.negative"
|
6208 | (dimensionsChanged)="updateYAxisWidth($event)"
|
6209 | ></svg:g>
|
6210 | <svg:g
|
6211 | *ngFor="let group of results; let index = index; trackBy: trackBy"
|
6212 | [@animationState]="'active'"
|
6213 | [attr.transform]="groupTransform(group)"
|
6214 | >
|
6215 | <svg:g
|
6216 | ngx-charts-series-horizontal
|
6217 | [xScale]="valueScale"
|
6218 | [activeEntries]="activeEntries"
|
6219 | [yScale]="innerScale"
|
6220 | [colors]="colors"
|
6221 | [series]="group.series"
|
6222 | [dims]="dims"
|
6223 | [gradient]="gradient"
|
6224 | [tooltipDisabled]="tooltipDisabled"
|
6225 | [tooltipTemplate]="tooltipTemplate"
|
6226 | [seriesName]="group.name"
|
6227 | [roundEdges]="roundEdges"
|
6228 | [animations]="animations"
|
6229 | [showDataLabel]="showDataLabel"
|
6230 | [dataLabelFormatting]="dataLabelFormatting"
|
6231 | [noBarWhenZero]="noBarWhenZero"
|
6232 | (select)="onClick($event, group)"
|
6233 | (activate)="onActivate($event, group)"
|
6234 | (deactivate)="onDeactivate($event, group)"
|
6235 | (dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
6236 | />
|
6237 | </svg:g>
|
6238 | </svg:g>
|
6239 | </ngx-charts-chart>
|
6240 | `,
|
6241 | changeDetection: ChangeDetectionStrategy.OnPush,
|
6242 | encapsulation: ViewEncapsulation.None,
|
6243 | animations: [
|
6244 | trigger('animationState', [
|
6245 | transition(':leave', [
|
6246 | style({
|
6247 | opacity: 1,
|
6248 | transform: '*'
|
6249 | }),
|
6250 | animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
6251 | ])
|
6252 | ])
|
6253 | ],
|
6254 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
6255 | },] }
|
6256 | ];
|
6257 | BarHorizontal2DComponent.propDecorators = {
|
6258 | legend: [{ type: Input }],
|
6259 | legendTitle: [{ type: Input }],
|
6260 | legendPosition: [{ type: Input }],
|
6261 | xAxis: [{ type: Input }],
|
6262 | yAxis: [{ type: Input }],
|
6263 | showXAxisLabel: [{ type: Input }],
|
6264 | showYAxisLabel: [{ type: Input }],
|
6265 | xAxisLabel: [{ type: Input }],
|
6266 | yAxisLabel: [{ type: Input }],
|
6267 | tooltipDisabled: [{ type: Input }],
|
6268 | gradient: [{ type: Input }],
|
6269 | showGridLines: [{ type: Input }],
|
6270 | activeEntries: [{ type: Input }],
|
6271 | schemeType: [{ type: Input }],
|
6272 | trimXAxisTicks: [{ type: Input }],
|
6273 | trimYAxisTicks: [{ type: Input }],
|
6274 | rotateXAxisTicks: [{ type: Input }],
|
6275 | maxXAxisTickLength: [{ type: Input }],
|
6276 | maxYAxisTickLength: [{ type: Input }],
|
6277 | xAxisTickFormatting: [{ type: Input }],
|
6278 | yAxisTickFormatting: [{ type: Input }],
|
6279 | xAxisTicks: [{ type: Input }],
|
6280 | yAxisTicks: [{ type: Input }],
|
6281 | groupPadding: [{ type: Input }],
|
6282 | barPadding: [{ type: Input }],
|
6283 | roundDomains: [{ type: Input }],
|
6284 | roundEdges: [{ type: Input }],
|
6285 | xScaleMax: [{ type: Input }],
|
6286 | showDataLabel: [{ type: Input }],
|
6287 | dataLabelFormatting: [{ type: Input }],
|
6288 | noBarWhenZero: [{ type: Input }],
|
6289 | activate: [{ type: Output }],
|
6290 | deactivate: [{ type: Output }],
|
6291 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
6292 | };
|
6293 |
|
6294 | var BarChartType;
|
6295 | (function (BarChartType) {
|
6296 | BarChartType["Standard"] = "standard";
|
6297 | BarChartType["Normalized"] = "normalized";
|
6298 | BarChartType["Stacked"] = "stacked";
|
6299 | })(BarChartType || (BarChartType = {}));
|
6300 |
|
6301 | class BarHorizontalNormalizedComponent extends BaseChartComponent {
|
6302 | constructor() {
|
6303 | super(...arguments);
|
6304 | this.legend = false;
|
6305 | this.legendTitle = 'Legend';
|
6306 | this.legendPosition = LegendPosition.Right;
|
6307 | this.tooltipDisabled = false;
|
6308 | this.showGridLines = true;
|
6309 | this.activeEntries = [];
|
6310 | this.trimXAxisTicks = true;
|
6311 | this.trimYAxisTicks = true;
|
6312 | this.rotateXAxisTicks = true;
|
6313 | this.maxXAxisTickLength = 16;
|
6314 | this.maxYAxisTickLength = 16;
|
6315 | this.barPadding = 8;
|
6316 | this.roundDomains = false;
|
6317 | this.noBarWhenZero = true;
|
6318 | this.activate = new EventEmitter();
|
6319 | this.deactivate = new EventEmitter();
|
6320 | this.valueDomain = [0, 100];
|
6321 | this.margin = [10, 20, 10, 20];
|
6322 | this.xAxisHeight = 0;
|
6323 | this.yAxisWidth = 0;
|
6324 | this.barChartType = BarChartType;
|
6325 | this.trackBy = (index, item) => {
|
6326 | return item.name;
|
6327 | };
|
6328 | }
|
6329 | update() {
|
6330 | super.update();
|
6331 | this.dims = calculateViewDimensions({
|
6332 | width: this.width,
|
6333 | height: this.height,
|
6334 | margins: this.margin,
|
6335 | showXAxis: this.xAxis,
|
6336 | showYAxis: this.yAxis,
|
6337 | xAxisHeight: this.xAxisHeight,
|
6338 | yAxisWidth: this.yAxisWidth,
|
6339 | showXLabel: this.showXAxisLabel,
|
6340 | showYLabel: this.showYAxisLabel,
|
6341 | showLegend: this.legend,
|
6342 | legendType: this.schemeType,
|
6343 | legendPosition: this.legendPosition
|
6344 | });
|
6345 | this.formatDates();
|
6346 | this.groupDomain = this.getGroupDomain();
|
6347 | this.innerDomain = this.getInnerDomain();
|
6348 | this.xScale = this.getXScale();
|
6349 | this.yScale = this.getYScale();
|
6350 | this.setColors();
|
6351 | this.legendOptions = this.getLegendOptions();
|
6352 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
6353 | }
|
6354 | getGroupDomain() {
|
6355 | const domain = [];
|
6356 | for (const group of this.results) {
|
6357 | if (!domain.includes(group.label)) {
|
6358 | domain.push(group.label);
|
6359 | }
|
6360 | }
|
6361 | return domain;
|
6362 | }
|
6363 | getInnerDomain() {
|
6364 | const domain = [];
|
6365 | for (const group of this.results) {
|
6366 | for (const d of group.series) {
|
6367 | if (!domain.includes(d.label)) {
|
6368 | domain.push(d.label);
|
6369 | }
|
6370 | }
|
6371 | }
|
6372 | return domain;
|
6373 | }
|
6374 | getYScale() {
|
6375 | const spacing = this.groupDomain.length / (this.dims.height / this.barPadding + 1);
|
6376 | return scaleBand().rangeRound([0, this.dims.height]).paddingInner(spacing).domain(this.groupDomain);
|
6377 | }
|
6378 | getXScale() {
|
6379 | const scale = scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
6380 | return this.roundDomains ? scale.nice() : scale;
|
6381 | }
|
6382 | groupTransform(group) {
|
6383 | return `translate(0, ${this.yScale(group.name)})`;
|
6384 | }
|
6385 | onClick(data, group) {
|
6386 | if (group) {
|
6387 | data.series = group.name;
|
6388 | }
|
6389 | this.select.emit(data);
|
6390 | }
|
6391 | setColors() {
|
6392 | let domain;
|
6393 | if (this.schemeType === ScaleType.Ordinal) {
|
6394 | domain = this.innerDomain;
|
6395 | }
|
6396 | else {
|
6397 | domain = this.valueDomain;
|
6398 | }
|
6399 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
6400 | }
|
6401 | getLegendOptions() {
|
6402 | const opts = {
|
6403 | scaleType: this.schemeType,
|
6404 | colors: undefined,
|
6405 | domain: [],
|
6406 | title: undefined,
|
6407 | position: this.legendPosition
|
6408 | };
|
6409 | if (opts.scaleType === ScaleType.Ordinal) {
|
6410 | opts.domain = this.innerDomain;
|
6411 | opts.colors = this.colors;
|
6412 | opts.title = this.legendTitle;
|
6413 | }
|
6414 | else {
|
6415 | opts.domain = this.valueDomain;
|
6416 | opts.colors = this.colors.scale;
|
6417 | }
|
6418 | return opts;
|
6419 | }
|
6420 | updateYAxisWidth({ width }) {
|
6421 | this.yAxisWidth = width;
|
6422 | this.update();
|
6423 | }
|
6424 | updateXAxisHeight({ height }) {
|
6425 | this.xAxisHeight = height;
|
6426 | this.update();
|
6427 | }
|
6428 | onActivate(event, group, fromLegend = false) {
|
6429 | const item = Object.assign({}, event);
|
6430 | if (group) {
|
6431 | item.series = group.name;
|
6432 | }
|
6433 | const items = this.results
|
6434 | .map(g => g.series)
|
6435 | .flat()
|
6436 | .filter(i => {
|
6437 | if (fromLegend) {
|
6438 | return i.label === item.name;
|
6439 | }
|
6440 | else {
|
6441 | return i.name === item.name && i.series === item.series;
|
6442 | }
|
6443 | });
|
6444 | this.activeEntries = [...items];
|
6445 | this.activate.emit({ value: item, entries: this.activeEntries });
|
6446 | }
|
6447 | onDeactivate(event, group, fromLegend = false) {
|
6448 | const item = Object.assign({}, event);
|
6449 | if (group) {
|
6450 | item.series = group.name;
|
6451 | }
|
6452 | this.activeEntries = this.activeEntries.filter(i => {
|
6453 | if (fromLegend) {
|
6454 | return i.label !== item.name;
|
6455 | }
|
6456 | else {
|
6457 | return !(i.name === item.name && i.series === item.series);
|
6458 | }
|
6459 | });
|
6460 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
6461 | }
|
6462 | }
|
6463 | BarHorizontalNormalizedComponent.decorators = [
|
6464 | { type: Component, args: [{
|
6465 | selector: 'ngx-charts-bar-horizontal-normalized',
|
6466 | template: `
|
6467 | <ngx-charts-chart
|
6468 | [view]="[width, height]"
|
6469 | [showLegend]="legend"
|
6470 | [legendOptions]="legendOptions"
|
6471 | [activeEntries]="activeEntries"
|
6472 | [animations]="animations"
|
6473 | (legendLabelActivate)="onActivate($event, undefined, true)"
|
6474 | (legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
6475 | (legendLabelClick)="onClick($event)"
|
6476 | >
|
6477 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
6478 | <svg:g
|
6479 | ngx-charts-x-axis
|
6480 | *ngIf="xAxis"
|
6481 | [xScale]="xScale"
|
6482 | [dims]="dims"
|
6483 | [showGridLines]="showGridLines"
|
6484 | [showLabel]="showXAxisLabel"
|
6485 | [labelText]="xAxisLabel"
|
6486 | [trimTicks]="trimXAxisTicks"
|
6487 | [rotateTicks]="rotateXAxisTicks"
|
6488 | [maxTickLength]="maxXAxisTickLength"
|
6489 | [tickFormatting]="xAxisTickFormatting"
|
6490 | [ticks]="xAxisTicks"
|
6491 | (dimensionsChanged)="updateXAxisHeight($event)"
|
6492 | ></svg:g>
|
6493 | <svg:g
|
6494 | ngx-charts-y-axis
|
6495 | *ngIf="yAxis"
|
6496 | [yScale]="yScale"
|
6497 | [dims]="dims"
|
6498 | [showLabel]="showYAxisLabel"
|
6499 | [labelText]="yAxisLabel"
|
6500 | [trimTicks]="trimYAxisTicks"
|
6501 | [maxTickLength]="maxYAxisTickLength"
|
6502 | [tickFormatting]="yAxisTickFormatting"
|
6503 | [ticks]="yAxisTicks"
|
6504 | (dimensionsChanged)="updateYAxisWidth($event)"
|
6505 | ></svg:g>
|
6506 | <svg:g
|
6507 | *ngFor="let group of results; trackBy: trackBy"
|
6508 | [@animationState]="'active'"
|
6509 | [attr.transform]="groupTransform(group)"
|
6510 | >
|
6511 | <svg:g
|
6512 | ngx-charts-series-horizontal
|
6513 | [type]="barChartType.Normalized"
|
6514 | [xScale]="xScale"
|
6515 | [yScale]="yScale"
|
6516 | [activeEntries]="activeEntries"
|
6517 | [colors]="colors"
|
6518 | [series]="group.series"
|
6519 | [dims]="dims"
|
6520 | [gradient]="gradient"
|
6521 | [tooltipDisabled]="tooltipDisabled"
|
6522 | [tooltipTemplate]="tooltipTemplate"
|
6523 | [seriesName]="group.name"
|
6524 | [animations]="animations"
|
6525 | (select)="onClick($event, group)"
|
6526 | (activate)="onActivate($event, group)"
|
6527 | (deactivate)="onDeactivate($event, group)"
|
6528 | [noBarWhenZero]="noBarWhenZero"
|
6529 | />
|
6530 | </svg:g>
|
6531 | </svg:g>
|
6532 | </ngx-charts-chart>
|
6533 | `,
|
6534 | changeDetection: ChangeDetectionStrategy.OnPush,
|
6535 | encapsulation: ViewEncapsulation.None,
|
6536 | animations: [
|
6537 | trigger('animationState', [
|
6538 | transition(':leave', [
|
6539 | style({
|
6540 | opacity: 1,
|
6541 | transform: '*'
|
6542 | }),
|
6543 | animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
6544 | ])
|
6545 | ])
|
6546 | ],
|
6547 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
6548 | },] }
|
6549 | ];
|
6550 | BarHorizontalNormalizedComponent.propDecorators = {
|
6551 | legend: [{ type: Input }],
|
6552 | legendTitle: [{ type: Input }],
|
6553 | legendPosition: [{ type: Input }],
|
6554 | xAxis: [{ type: Input }],
|
6555 | yAxis: [{ type: Input }],
|
6556 | showXAxisLabel: [{ type: Input }],
|
6557 | showYAxisLabel: [{ type: Input }],
|
6558 | xAxisLabel: [{ type: Input }],
|
6559 | yAxisLabel: [{ type: Input }],
|
6560 | tooltipDisabled: [{ type: Input }],
|
6561 | gradient: [{ type: Input }],
|
6562 | showGridLines: [{ type: Input }],
|
6563 | activeEntries: [{ type: Input }],
|
6564 | schemeType: [{ type: Input }],
|
6565 | trimXAxisTicks: [{ type: Input }],
|
6566 | trimYAxisTicks: [{ type: Input }],
|
6567 | rotateXAxisTicks: [{ type: Input }],
|
6568 | maxXAxisTickLength: [{ type: Input }],
|
6569 | maxYAxisTickLength: [{ type: Input }],
|
6570 | xAxisTickFormatting: [{ type: Input }],
|
6571 | yAxisTickFormatting: [{ type: Input }],
|
6572 | xAxisTicks: [{ type: Input }],
|
6573 | yAxisTicks: [{ type: Input }],
|
6574 | barPadding: [{ type: Input }],
|
6575 | roundDomains: [{ type: Input }],
|
6576 | noBarWhenZero: [{ type: Input }],
|
6577 | activate: [{ type: Output }],
|
6578 | deactivate: [{ type: Output }],
|
6579 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
6580 | };
|
6581 |
|
6582 | class BarHorizontalStackedComponent extends BaseChartComponent {
|
6583 | constructor() {
|
6584 | super(...arguments);
|
6585 | this.legend = false;
|
6586 | this.legendTitle = 'Legend';
|
6587 | this.legendPosition = LegendPosition.Right;
|
6588 | this.tooltipDisabled = false;
|
6589 | this.showGridLines = true;
|
6590 | this.activeEntries = [];
|
6591 | this.trimXAxisTicks = true;
|
6592 | this.trimYAxisTicks = true;
|
6593 | this.rotateXAxisTicks = true;
|
6594 | this.maxXAxisTickLength = 16;
|
6595 | this.maxYAxisTickLength = 16;
|
6596 | this.barPadding = 8;
|
6597 | this.roundDomains = false;
|
6598 | this.showDataLabel = false;
|
6599 | this.noBarWhenZero = true;
|
6600 | this.activate = new EventEmitter();
|
6601 | this.deactivate = new EventEmitter();
|
6602 | this.margin = [10, 20, 10, 20];
|
6603 | this.xAxisHeight = 0;
|
6604 | this.yAxisWidth = 0;
|
6605 | this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
6606 | this.barChartType = BarChartType;
|
6607 | this.trackBy = (index, item) => {
|
6608 | return item.name;
|
6609 | };
|
6610 | }
|
6611 | update() {
|
6612 | super.update();
|
6613 | if (!this.showDataLabel) {
|
6614 | this.dataLabelMaxWidth = { negative: 0, positive: 0 };
|
6615 | }
|
6616 | this.margin = [10, 20 + this.dataLabelMaxWidth.positive, 10, 20 + this.dataLabelMaxWidth.negative];
|
6617 | this.dims = calculateViewDimensions({
|
6618 | width: this.width,
|
6619 | height: this.height,
|
6620 | margins: this.margin,
|
6621 | showXAxis: this.xAxis,
|
6622 | showYAxis: this.yAxis,
|
6623 | xAxisHeight: this.xAxisHeight,
|
6624 | yAxisWidth: this.yAxisWidth,
|
6625 | showXLabel: this.showXAxisLabel,
|
6626 | showYLabel: this.showYAxisLabel,
|
6627 | showLegend: this.legend,
|
6628 | legendType: this.schemeType,
|
6629 | legendPosition: this.legendPosition
|
6630 | });
|
6631 | this.formatDates();
|
6632 | this.groupDomain = this.getGroupDomain();
|
6633 | this.innerDomain = this.getInnerDomain();
|
6634 | this.valueDomain = this.getValueDomain();
|
6635 | this.xScale = this.getXScale();
|
6636 | this.yScale = this.getYScale();
|
6637 | this.setColors();
|
6638 | this.legendOptions = this.getLegendOptions();
|
6639 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
6640 | }
|
6641 | getGroupDomain() {
|
6642 | const domain = [];
|
6643 | for (const group of this.results) {
|
6644 | if (!domain.includes(group.label)) {
|
6645 | domain.push(group.label);
|
6646 | }
|
6647 | }
|
6648 | return domain;
|
6649 | }
|
6650 | getInnerDomain() {
|
6651 | const domain = [];
|
6652 | for (const group of this.results) {
|
6653 | for (const d of group.series) {
|
6654 | if (!domain.includes(d.label)) {
|
6655 | domain.push(d.label);
|
6656 | }
|
6657 | }
|
6658 | }
|
6659 | return domain;
|
6660 | }
|
6661 | getValueDomain() {
|
6662 | const domain = [];
|
6663 | let smallest = 0;
|
6664 | let biggest = 0;
|
6665 | for (const group of this.results) {
|
6666 | let smallestSum = 0;
|
6667 | let biggestSum = 0;
|
6668 | for (const d of group.series) {
|
6669 | if (d.value < 0) {
|
6670 | smallestSum += d.value;
|
6671 | }
|
6672 | else {
|
6673 | biggestSum += d.value;
|
6674 | }
|
6675 | smallest = d.value < smallest ? d.value : smallest;
|
6676 | biggest = d.value > biggest ? d.value : biggest;
|
6677 | }
|
6678 | domain.push(smallestSum);
|
6679 | domain.push(biggestSum);
|
6680 | }
|
6681 | domain.push(smallest);
|
6682 | domain.push(biggest);
|
6683 | const min = Math.min(0, ...domain);
|
6684 | const max = this.xScaleMax ? Math.max(this.xScaleMax, ...domain) : Math.max(...domain);
|
6685 | return [min, max];
|
6686 | }
|
6687 | getYScale() {
|
6688 | const spacing = this.groupDomain.length / (this.dims.height / this.barPadding + 1);
|
6689 | return scaleBand().rangeRound([0, this.dims.height]).paddingInner(spacing).domain(this.groupDomain);
|
6690 | }
|
6691 | getXScale() {
|
6692 | const scale = scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
6693 | return this.roundDomains ? scale.nice() : scale;
|
6694 | }
|
6695 | groupTransform(group) {
|
6696 | return `translate(0, ${this.yScale(group.name)})`;
|
6697 | }
|
6698 | onClick(data, group) {
|
6699 | if (group) {
|
6700 | data.series = group.name;
|
6701 | }
|
6702 | this.select.emit(data);
|
6703 | }
|
6704 | setColors() {
|
6705 | let domain;
|
6706 | if (this.schemeType === ScaleType.Ordinal) {
|
6707 | domain = this.innerDomain;
|
6708 | }
|
6709 | else {
|
6710 | domain = this.valueDomain;
|
6711 | }
|
6712 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
6713 | }
|
6714 | getLegendOptions() {
|
6715 | const opts = {
|
6716 | scaleType: this.schemeType,
|
6717 | colors: undefined,
|
6718 | domain: [],
|
6719 | title: undefined,
|
6720 | position: this.legendPosition
|
6721 | };
|
6722 | if (opts.scaleType === ScaleType.Ordinal) {
|
6723 | opts.domain = this.innerDomain;
|
6724 | opts.colors = this.colors;
|
6725 | opts.title = this.legendTitle;
|
6726 | }
|
6727 | else {
|
6728 | opts.domain = this.valueDomain;
|
6729 | opts.colors = this.colors.scale;
|
6730 | }
|
6731 | return opts;
|
6732 | }
|
6733 | updateYAxisWidth({ width }) {
|
6734 | this.yAxisWidth = width;
|
6735 | this.update();
|
6736 | }
|
6737 | updateXAxisHeight({ height }) {
|
6738 | this.xAxisHeight = height;
|
6739 | this.update();
|
6740 | }
|
6741 | onDataLabelMaxWidthChanged(event, groupIndex) {
|
6742 | if (event.size.negative) {
|
6743 | this.dataLabelMaxWidth.negative = Math.max(this.dataLabelMaxWidth.negative, event.size.width);
|
6744 | }
|
6745 | else {
|
6746 | this.dataLabelMaxWidth.positive = Math.max(this.dataLabelMaxWidth.positive, event.size.width);
|
6747 | }
|
6748 | if (groupIndex === this.results.length - 1) {
|
6749 | setTimeout(() => this.update());
|
6750 | }
|
6751 | }
|
6752 | onActivate(event, group, fromLegend = false) {
|
6753 | const item = Object.assign({}, event);
|
6754 | if (group) {
|
6755 | item.series = group.name;
|
6756 | }
|
6757 | const items = this.results
|
6758 | .map(g => g.series)
|
6759 | .flat()
|
6760 | .filter(i => {
|
6761 | if (fromLegend) {
|
6762 | return i.label === item.name;
|
6763 | }
|
6764 | else {
|
6765 | return i.name === item.name && i.series === item.series;
|
6766 | }
|
6767 | });
|
6768 | this.activeEntries = [...items];
|
6769 | this.activate.emit({ value: item, entries: this.activeEntries });
|
6770 | }
|
6771 | onDeactivate(event, group, fromLegend = false) {
|
6772 | const item = Object.assign({}, event);
|
6773 | if (group) {
|
6774 | item.series = group.name;
|
6775 | }
|
6776 | this.activeEntries = this.activeEntries.filter(i => {
|
6777 | if (fromLegend) {
|
6778 | return i.label !== item.name;
|
6779 | }
|
6780 | else {
|
6781 | return !(i.name === item.name && i.series === item.series);
|
6782 | }
|
6783 | });
|
6784 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
6785 | }
|
6786 | }
|
6787 | BarHorizontalStackedComponent.decorators = [
|
6788 | { type: Component, args: [{
|
6789 | selector: 'ngx-charts-bar-horizontal-stacked',
|
6790 | template: `
|
6791 | <ngx-charts-chart
|
6792 | [view]="[width, height]"
|
6793 | [showLegend]="legend"
|
6794 | [legendOptions]="legendOptions"
|
6795 | [activeEntries]="activeEntries"
|
6796 | [animations]="animations"
|
6797 | (legendLabelActivate)="onActivate($event, undefined, true)"
|
6798 | (legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
6799 | (legendLabelClick)="onClick($event)"
|
6800 | >
|
6801 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
6802 | <svg:g
|
6803 | ngx-charts-x-axis
|
6804 | *ngIf="xAxis"
|
6805 | [xScale]="xScale"
|
6806 | [dims]="dims"
|
6807 | [showGridLines]="showGridLines"
|
6808 | [showLabel]="showXAxisLabel"
|
6809 | [labelText]="xAxisLabel"
|
6810 | [trimTicks]="trimXAxisTicks"
|
6811 | [rotateTicks]="rotateXAxisTicks"
|
6812 | [maxTickLength]="maxXAxisTickLength"
|
6813 | [tickFormatting]="xAxisTickFormatting"
|
6814 | [ticks]="xAxisTicks"
|
6815 | (dimensionsChanged)="updateXAxisHeight($event)"
|
6816 | ></svg:g>
|
6817 | <svg:g
|
6818 | ngx-charts-y-axis
|
6819 | *ngIf="yAxis"
|
6820 | [yScale]="yScale"
|
6821 | [dims]="dims"
|
6822 | [showLabel]="showYAxisLabel"
|
6823 | [labelText]="yAxisLabel"
|
6824 | [trimTicks]="trimYAxisTicks"
|
6825 | [maxTickLength]="maxYAxisTickLength"
|
6826 | [tickFormatting]="yAxisTickFormatting"
|
6827 | [ticks]="yAxisTicks"
|
6828 | [yAxisOffset]="dataLabelMaxWidth.negative"
|
6829 | (dimensionsChanged)="updateYAxisWidth($event)"
|
6830 | ></svg:g>
|
6831 | <svg:g
|
6832 | *ngFor="let group of results; let index = index; trackBy: trackBy"
|
6833 | [@animationState]="'active'"
|
6834 | [attr.transform]="groupTransform(group)"
|
6835 | >
|
6836 | <svg:g
|
6837 | ngx-charts-series-horizontal
|
6838 | [type]="barChartType.Stacked"
|
6839 | [xScale]="xScale"
|
6840 | [yScale]="yScale"
|
6841 | [colors]="colors"
|
6842 | [series]="group.series"
|
6843 | [activeEntries]="activeEntries"
|
6844 | [dims]="dims"
|
6845 | [gradient]="gradient"
|
6846 | [tooltipDisabled]="tooltipDisabled"
|
6847 | [tooltipTemplate]="tooltipTemplate"
|
6848 | [seriesName]="group.name"
|
6849 | [animations]="animations"
|
6850 | [showDataLabel]="showDataLabel"
|
6851 | [dataLabelFormatting]="dataLabelFormatting"
|
6852 | [noBarWhenZero]="noBarWhenZero"
|
6853 | (select)="onClick($event, group)"
|
6854 | (activate)="onActivate($event, group)"
|
6855 | (deactivate)="onDeactivate($event, group)"
|
6856 | (dataLabelWidthChanged)="onDataLabelMaxWidthChanged($event, index)"
|
6857 | />
|
6858 | </svg:g>
|
6859 | </svg:g>
|
6860 | </ngx-charts-chart>
|
6861 | `,
|
6862 | changeDetection: ChangeDetectionStrategy.OnPush,
|
6863 | encapsulation: ViewEncapsulation.None,
|
6864 | animations: [
|
6865 | trigger('animationState', [
|
6866 | transition(':leave', [
|
6867 | style({
|
6868 | opacity: 1,
|
6869 | transform: '*'
|
6870 | }),
|
6871 | animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
6872 | ])
|
6873 | ])
|
6874 | ],
|
6875 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
6876 | },] }
|
6877 | ];
|
6878 | BarHorizontalStackedComponent.propDecorators = {
|
6879 | legend: [{ type: Input }],
|
6880 | legendTitle: [{ type: Input }],
|
6881 | legendPosition: [{ type: Input }],
|
6882 | xAxis: [{ type: Input }],
|
6883 | yAxis: [{ type: Input }],
|
6884 | showXAxisLabel: [{ type: Input }],
|
6885 | showYAxisLabel: [{ type: Input }],
|
6886 | xAxisLabel: [{ type: Input }],
|
6887 | yAxisLabel: [{ type: Input }],
|
6888 | tooltipDisabled: [{ type: Input }],
|
6889 | gradient: [{ type: Input }],
|
6890 | showGridLines: [{ type: Input }],
|
6891 | activeEntries: [{ type: Input }],
|
6892 | schemeType: [{ type: Input }],
|
6893 | trimXAxisTicks: [{ type: Input }],
|
6894 | trimYAxisTicks: [{ type: Input }],
|
6895 | rotateXAxisTicks: [{ type: Input }],
|
6896 | maxXAxisTickLength: [{ type: Input }],
|
6897 | maxYAxisTickLength: [{ type: Input }],
|
6898 | xAxisTickFormatting: [{ type: Input }],
|
6899 | yAxisTickFormatting: [{ type: Input }],
|
6900 | xAxisTicks: [{ type: Input }],
|
6901 | yAxisTicks: [{ type: Input }],
|
6902 | barPadding: [{ type: Input }],
|
6903 | roundDomains: [{ type: Input }],
|
6904 | xScaleMax: [{ type: Input }],
|
6905 | showDataLabel: [{ type: Input }],
|
6906 | dataLabelFormatting: [{ type: Input }],
|
6907 | noBarWhenZero: [{ type: Input }],
|
6908 | activate: [{ type: Output }],
|
6909 | deactivate: [{ type: Output }],
|
6910 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
6911 | };
|
6912 |
|
6913 | class BarVerticalComponent extends BaseChartComponent {
|
6914 | constructor() {
|
6915 | super(...arguments);
|
6916 | this.legend = false;
|
6917 | this.legendTitle = 'Legend';
|
6918 | this.legendPosition = LegendPosition.Right;
|
6919 | this.tooltipDisabled = false;
|
6920 | this.showGridLines = true;
|
6921 | this.activeEntries = [];
|
6922 | this.trimXAxisTicks = true;
|
6923 | this.trimYAxisTicks = true;
|
6924 | this.rotateXAxisTicks = true;
|
6925 | this.maxXAxisTickLength = 16;
|
6926 | this.maxYAxisTickLength = 16;
|
6927 | this.barPadding = 8;
|
6928 | this.roundDomains = false;
|
6929 | this.roundEdges = true;
|
6930 | this.showDataLabel = false;
|
6931 | this.noBarWhenZero = true;
|
6932 | this.activate = new EventEmitter();
|
6933 | this.deactivate = new EventEmitter();
|
6934 | this.margin = [10, 20, 10, 20];
|
6935 | this.xAxisHeight = 0;
|
6936 | this.yAxisWidth = 0;
|
6937 | this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
6938 | }
|
6939 | update() {
|
6940 | super.update();
|
6941 | if (!this.showDataLabel) {
|
6942 | this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
6943 | }
|
6944 | this.margin = [10 + this.dataLabelMaxHeight.positive, 20, 10 + this.dataLabelMaxHeight.negative, 20];
|
6945 | this.dims = calculateViewDimensions({
|
6946 | width: this.width,
|
6947 | height: this.height,
|
6948 | margins: this.margin,
|
6949 | showXAxis: this.xAxis,
|
6950 | showYAxis: this.yAxis,
|
6951 | xAxisHeight: this.xAxisHeight,
|
6952 | yAxisWidth: this.yAxisWidth,
|
6953 | showXLabel: this.showXAxisLabel,
|
6954 | showYLabel: this.showYAxisLabel,
|
6955 | showLegend: this.legend,
|
6956 | legendType: this.schemeType,
|
6957 | legendPosition: this.legendPosition
|
6958 | });
|
6959 | this.formatDates();
|
6960 | if (this.showDataLabel) {
|
6961 | this.dims.height -= this.dataLabelMaxHeight.negative;
|
6962 | }
|
6963 | this.xScale = this.getXScale();
|
6964 | this.yScale = this.getYScale();
|
6965 | this.setColors();
|
6966 | this.legendOptions = this.getLegendOptions();
|
6967 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0] + this.dataLabelMaxHeight.negative})`;
|
6968 | }
|
6969 | getXScale() {
|
6970 | this.xDomain = this.getXDomain();
|
6971 | const spacing = this.xDomain.length / (this.dims.width / this.barPadding + 1);
|
6972 | return scaleBand().range([0, this.dims.width]).paddingInner(spacing).domain(this.xDomain);
|
6973 | }
|
6974 | getYScale() {
|
6975 | this.yDomain = this.getYDomain();
|
6976 | const scale = scaleLinear().range([this.dims.height, 0]).domain(this.yDomain);
|
6977 | return this.roundDomains ? scale.nice() : scale;
|
6978 | }
|
6979 | getXDomain() {
|
6980 | return this.results.map(d => d.label);
|
6981 | }
|
6982 | getYDomain() {
|
6983 | const values = this.results.map(d => d.value);
|
6984 | let min = this.yScaleMin ? Math.min(this.yScaleMin, ...values) : Math.min(0, ...values);
|
6985 | if (this.yAxisTicks && !this.yAxisTicks.some(isNaN)) {
|
6986 | min = Math.min(min, ...this.yAxisTicks);
|
6987 | }
|
6988 | let max = this.yScaleMax ? Math.max(this.yScaleMax, ...values) : Math.max(0, ...values);
|
6989 | if (this.yAxisTicks && !this.yAxisTicks.some(isNaN)) {
|
6990 | max = Math.max(max, ...this.yAxisTicks);
|
6991 | }
|
6992 | return [min, max];
|
6993 | }
|
6994 | onClick(data) {
|
6995 | this.select.emit(data);
|
6996 | }
|
6997 | setColors() {
|
6998 | let domain;
|
6999 | if (this.schemeType === ScaleType.Ordinal) {
|
7000 | domain = this.xDomain;
|
7001 | }
|
7002 | else {
|
7003 | domain = this.yDomain;
|
7004 | }
|
7005 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
7006 | }
|
7007 | getLegendOptions() {
|
7008 | const opts = {
|
7009 | scaleType: this.schemeType,
|
7010 | colors: undefined,
|
7011 | domain: [],
|
7012 | title: undefined,
|
7013 | position: this.legendPosition
|
7014 | };
|
7015 | if (opts.scaleType === ScaleType.Ordinal) {
|
7016 | opts.domain = this.xDomain;
|
7017 | opts.colors = this.colors;
|
7018 | opts.title = this.legendTitle;
|
7019 | }
|
7020 | else {
|
7021 | opts.domain = this.yDomain;
|
7022 | opts.colors = this.colors.scale;
|
7023 | }
|
7024 | return opts;
|
7025 | }
|
7026 | updateYAxisWidth({ width }) {
|
7027 | this.yAxisWidth = width;
|
7028 | this.update();
|
7029 | }
|
7030 | updateXAxisHeight({ height }) {
|
7031 | this.xAxisHeight = height;
|
7032 | this.update();
|
7033 | }
|
7034 | onDataLabelMaxHeightChanged(event) {
|
7035 | if (event.size.negative) {
|
7036 | this.dataLabelMaxHeight.negative = Math.max(this.dataLabelMaxHeight.negative, event.size.height);
|
7037 | }
|
7038 | else {
|
7039 | this.dataLabelMaxHeight.positive = Math.max(this.dataLabelMaxHeight.positive, event.size.height);
|
7040 | }
|
7041 | if (event.index === this.results.length - 1) {
|
7042 | setTimeout(() => this.update());
|
7043 | }
|
7044 | }
|
7045 | onActivate(item, fromLegend = false) {
|
7046 | item = this.results.find(d => {
|
7047 | if (fromLegend) {
|
7048 | return d.label === item.name;
|
7049 | }
|
7050 | else {
|
7051 | return d.name === item.name;
|
7052 | }
|
7053 | });
|
7054 | const idx = this.activeEntries.findIndex(d => {
|
7055 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
7056 | });
|
7057 | if (idx > -1) {
|
7058 | return;
|
7059 | }
|
7060 | this.activeEntries = [item, ...this.activeEntries];
|
7061 | this.activate.emit({ value: item, entries: this.activeEntries });
|
7062 | }
|
7063 | onDeactivate(item, fromLegend = false) {
|
7064 | item = this.results.find(d => {
|
7065 | if (fromLegend) {
|
7066 | return d.label === item.name;
|
7067 | }
|
7068 | else {
|
7069 | return d.name === item.name;
|
7070 | }
|
7071 | });
|
7072 | const idx = this.activeEntries.findIndex(d => {
|
7073 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
7074 | });
|
7075 | this.activeEntries.splice(idx, 1);
|
7076 | this.activeEntries = [...this.activeEntries];
|
7077 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
7078 | }
|
7079 | }
|
7080 | BarVerticalComponent.decorators = [
|
7081 | { type: Component, args: [{
|
7082 | selector: 'ngx-charts-bar-vertical',
|
7083 | template: `
|
7084 | <ngx-charts-chart
|
7085 | [view]="[width, height]"
|
7086 | [showLegend]="legend"
|
7087 | [legendOptions]="legendOptions"
|
7088 | [activeEntries]="activeEntries"
|
7089 | [animations]="animations"
|
7090 | (legendLabelClick)="onClick($event)"
|
7091 | (legendLabelActivate)="onActivate($event, true)"
|
7092 | (legendLabelDeactivate)="onDeactivate($event, true)"
|
7093 | >
|
7094 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
7095 | <svg:g
|
7096 | ngx-charts-x-axis
|
7097 | *ngIf="xAxis"
|
7098 | [xScale]="xScale"
|
7099 | [dims]="dims"
|
7100 | [showGridLines]="showGridLines"
|
7101 | [showLabel]="showXAxisLabel"
|
7102 | [labelText]="xAxisLabel"
|
7103 | [trimTicks]="trimXAxisTicks"
|
7104 | [rotateTicks]="rotateXAxisTicks"
|
7105 | [maxTickLength]="maxXAxisTickLength"
|
7106 | [tickFormatting]="xAxisTickFormatting"
|
7107 | [ticks]="xAxisTicks"
|
7108 | [xAxisOffset]="dataLabelMaxHeight.negative"
|
7109 | (dimensionsChanged)="updateXAxisHeight($event)"
|
7110 | ></svg:g>
|
7111 | <svg:g
|
7112 | ngx-charts-y-axis
|
7113 | *ngIf="yAxis"
|
7114 | [yScale]="yScale"
|
7115 | [dims]="dims"
|
7116 | [showGridLines]="showGridLines"
|
7117 | [showLabel]="showYAxisLabel"
|
7118 | [labelText]="yAxisLabel"
|
7119 | [trimTicks]="trimYAxisTicks"
|
7120 | [maxTickLength]="maxYAxisTickLength"
|
7121 | [tickFormatting]="yAxisTickFormatting"
|
7122 | [ticks]="yAxisTicks"
|
7123 | (dimensionsChanged)="updateYAxisWidth($event)"
|
7124 | ></svg:g>
|
7125 | <svg:g
|
7126 | ngx-charts-series-vertical
|
7127 | [xScale]="xScale"
|
7128 | [yScale]="yScale"
|
7129 | [colors]="colors"
|
7130 | [series]="results"
|
7131 | [dims]="dims"
|
7132 | [gradient]="gradient"
|
7133 | [tooltipDisabled]="tooltipDisabled"
|
7134 | [tooltipTemplate]="tooltipTemplate"
|
7135 | [showDataLabel]="showDataLabel"
|
7136 | [dataLabelFormatting]="dataLabelFormatting"
|
7137 | [activeEntries]="activeEntries"
|
7138 | [roundEdges]="roundEdges"
|
7139 | [animations]="animations"
|
7140 | [noBarWhenZero]="noBarWhenZero"
|
7141 | (activate)="onActivate($event)"
|
7142 | (deactivate)="onDeactivate($event)"
|
7143 | (select)="onClick($event)"
|
7144 | (dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event)"
|
7145 | ></svg:g>
|
7146 | </svg:g>
|
7147 | </ngx-charts-chart>
|
7148 | `,
|
7149 | changeDetection: ChangeDetectionStrategy.OnPush,
|
7150 | encapsulation: ViewEncapsulation.None,
|
7151 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
7152 | },] }
|
7153 | ];
|
7154 | BarVerticalComponent.propDecorators = {
|
7155 | legend: [{ type: Input }],
|
7156 | legendTitle: [{ type: Input }],
|
7157 | legendPosition: [{ type: Input }],
|
7158 | xAxis: [{ type: Input }],
|
7159 | yAxis: [{ type: Input }],
|
7160 | showXAxisLabel: [{ type: Input }],
|
7161 | showYAxisLabel: [{ type: Input }],
|
7162 | xAxisLabel: [{ type: Input }],
|
7163 | yAxisLabel: [{ type: Input }],
|
7164 | tooltipDisabled: [{ type: Input }],
|
7165 | gradient: [{ type: Input }],
|
7166 | showGridLines: [{ type: Input }],
|
7167 | activeEntries: [{ type: Input }],
|
7168 | schemeType: [{ type: Input }],
|
7169 | trimXAxisTicks: [{ type: Input }],
|
7170 | trimYAxisTicks: [{ type: Input }],
|
7171 | rotateXAxisTicks: [{ type: Input }],
|
7172 | maxXAxisTickLength: [{ type: Input }],
|
7173 | maxYAxisTickLength: [{ type: Input }],
|
7174 | xAxisTickFormatting: [{ type: Input }],
|
7175 | yAxisTickFormatting: [{ type: Input }],
|
7176 | xAxisTicks: [{ type: Input }],
|
7177 | yAxisTicks: [{ type: Input }],
|
7178 | barPadding: [{ type: Input }],
|
7179 | roundDomains: [{ type: Input }],
|
7180 | roundEdges: [{ type: Input }],
|
7181 | yScaleMax: [{ type: Input }],
|
7182 | yScaleMin: [{ type: Input }],
|
7183 | showDataLabel: [{ type: Input }],
|
7184 | dataLabelFormatting: [{ type: Input }],
|
7185 | noBarWhenZero: [{ type: Input }],
|
7186 | activate: [{ type: Output }],
|
7187 | deactivate: [{ type: Output }],
|
7188 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
7189 | };
|
7190 |
|
7191 | class BarVertical2DComponent extends BaseChartComponent {
|
7192 | constructor() {
|
7193 | super(...arguments);
|
7194 | this.legend = false;
|
7195 | this.legendTitle = 'Legend';
|
7196 | this.legendPosition = LegendPosition.Right;
|
7197 | this.tooltipDisabled = false;
|
7198 | this.scaleType = ScaleType.Ordinal;
|
7199 | this.showGridLines = true;
|
7200 | this.activeEntries = [];
|
7201 | this.trimXAxisTicks = true;
|
7202 | this.trimYAxisTicks = true;
|
7203 | this.rotateXAxisTicks = true;
|
7204 | this.maxXAxisTickLength = 16;
|
7205 | this.maxYAxisTickLength = 16;
|
7206 | this.groupPadding = 16;
|
7207 | this.barPadding = 8;
|
7208 | this.roundDomains = false;
|
7209 | this.roundEdges = true;
|
7210 | this.showDataLabel = false;
|
7211 | this.noBarWhenZero = true;
|
7212 | this.activate = new EventEmitter();
|
7213 | this.deactivate = new EventEmitter();
|
7214 | this.margin = [10, 20, 10, 20];
|
7215 | this.xAxisHeight = 0;
|
7216 | this.yAxisWidth = 0;
|
7217 | this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
7218 | this.barOrientation = BarOrientation;
|
7219 | this.trackBy = (index, item) => {
|
7220 | return item.name;
|
7221 | };
|
7222 | }
|
7223 | update() {
|
7224 | super.update();
|
7225 | if (!this.showDataLabel) {
|
7226 | this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
7227 | }
|
7228 | this.margin = [10 + this.dataLabelMaxHeight.positive, 20, 10 + this.dataLabelMaxHeight.negative, 20];
|
7229 | this.dims = calculateViewDimensions({
|
7230 | width: this.width,
|
7231 | height: this.height,
|
7232 | margins: this.margin,
|
7233 | showXAxis: this.xAxis,
|
7234 | showYAxis: this.yAxis,
|
7235 | xAxisHeight: this.xAxisHeight,
|
7236 | yAxisWidth: this.yAxisWidth,
|
7237 | showXLabel: this.showXAxisLabel,
|
7238 | showYLabel: this.showYAxisLabel,
|
7239 | showLegend: this.legend,
|
7240 | legendType: this.schemeType,
|
7241 | legendPosition: this.legendPosition
|
7242 | });
|
7243 | if (this.showDataLabel) {
|
7244 | this.dims.height -= this.dataLabelMaxHeight.negative;
|
7245 | }
|
7246 | this.formatDates();
|
7247 | this.groupDomain = this.getGroupDomain();
|
7248 | this.innerDomain = this.getInnerDomain();
|
7249 | this.valueDomain = this.getValueDomain();
|
7250 | this.groupScale = this.getGroupScale();
|
7251 | this.innerScale = this.getInnerScale();
|
7252 | this.valueScale = this.getValueScale();
|
7253 | this.setColors();
|
7254 | this.legendOptions = this.getLegendOptions();
|
7255 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0] + this.dataLabelMaxHeight.negative})`;
|
7256 | }
|
7257 | onDataLabelMaxHeightChanged(event, groupIndex) {
|
7258 | if (event.size.negative) {
|
7259 | this.dataLabelMaxHeight.negative = Math.max(this.dataLabelMaxHeight.negative, event.size.height);
|
7260 | }
|
7261 | else {
|
7262 | this.dataLabelMaxHeight.positive = Math.max(this.dataLabelMaxHeight.positive, event.size.height);
|
7263 | }
|
7264 | if (groupIndex === this.results.length - 1) {
|
7265 | setTimeout(() => this.update());
|
7266 | }
|
7267 | }
|
7268 | getGroupScale() {
|
7269 | const spacing = this.groupDomain.length / (this.dims.height / this.groupPadding + 1);
|
7270 | return scaleBand()
|
7271 | .rangeRound([0, this.dims.width])
|
7272 | .paddingInner(spacing)
|
7273 | .paddingOuter(spacing / 2)
|
7274 | .domain(this.groupDomain);
|
7275 | }
|
7276 | getInnerScale() {
|
7277 | const width = this.groupScale.bandwidth();
|
7278 | const spacing = this.innerDomain.length / (width / this.barPadding + 1);
|
7279 | return scaleBand().rangeRound([0, width]).paddingInner(spacing).domain(this.innerDomain);
|
7280 | }
|
7281 | getValueScale() {
|
7282 | const scale = scaleLinear().range([this.dims.height, 0]).domain(this.valueDomain);
|
7283 | return this.roundDomains ? scale.nice() : scale;
|
7284 | }
|
7285 | getGroupDomain() {
|
7286 | const domain = [];
|
7287 | for (const group of this.results) {
|
7288 | if (!domain.includes(group.label)) {
|
7289 | domain.push(group.label);
|
7290 | }
|
7291 | }
|
7292 | return domain;
|
7293 | }
|
7294 | getInnerDomain() {
|
7295 | const domain = [];
|
7296 | for (const group of this.results) {
|
7297 | for (const d of group.series) {
|
7298 | if (!domain.includes(d.label)) {
|
7299 | domain.push(d.label);
|
7300 | }
|
7301 | }
|
7302 | }
|
7303 | return domain;
|
7304 | }
|
7305 | getValueDomain() {
|
7306 | const domain = [];
|
7307 | for (const group of this.results) {
|
7308 | for (const d of group.series) {
|
7309 | if (!domain.includes(d.value)) {
|
7310 | domain.push(d.value);
|
7311 | }
|
7312 | }
|
7313 | }
|
7314 | const min = Math.min(0, ...domain);
|
7315 | const max = this.yScaleMax ? Math.max(this.yScaleMax, ...domain) : Math.max(0, ...domain);
|
7316 | return [min, max];
|
7317 | }
|
7318 | groupTransform(group) {
|
7319 | return `translate(${this.groupScale(group.label)}, 0)`;
|
7320 | }
|
7321 | onClick(data, group) {
|
7322 | if (group) {
|
7323 | data.series = group.name;
|
7324 | }
|
7325 | this.select.emit(data);
|
7326 | }
|
7327 | setColors() {
|
7328 | let domain;
|
7329 | if (this.schemeType === ScaleType.Ordinal) {
|
7330 | domain = this.innerDomain;
|
7331 | }
|
7332 | else {
|
7333 | domain = this.valueDomain;
|
7334 | }
|
7335 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
7336 | }
|
7337 | getLegendOptions() {
|
7338 | const opts = {
|
7339 | scaleType: this.schemeType,
|
7340 | colors: undefined,
|
7341 | domain: [],
|
7342 | title: undefined,
|
7343 | position: this.legendPosition
|
7344 | };
|
7345 | if (opts.scaleType === ScaleType.Ordinal) {
|
7346 | opts.domain = this.innerDomain;
|
7347 | opts.colors = this.colors;
|
7348 | opts.title = this.legendTitle;
|
7349 | }
|
7350 | else {
|
7351 | opts.domain = this.valueDomain;
|
7352 | opts.colors = this.colors.scale;
|
7353 | }
|
7354 | return opts;
|
7355 | }
|
7356 | updateYAxisWidth({ width }) {
|
7357 | this.yAxisWidth = width;
|
7358 | this.update();
|
7359 | }
|
7360 | updateXAxisHeight({ height }) {
|
7361 | this.xAxisHeight = height;
|
7362 | this.update();
|
7363 | }
|
7364 | onActivate(event, group, fromLegend = false) {
|
7365 | const item = Object.assign({}, event);
|
7366 | if (group) {
|
7367 | item.series = group.name;
|
7368 | }
|
7369 | const items = this.results
|
7370 | .map(g => g.series)
|
7371 | .flat()
|
7372 | .filter(i => {
|
7373 | if (fromLegend) {
|
7374 | return i.label === item.name;
|
7375 | }
|
7376 | else {
|
7377 | return i.name === item.name && i.series === item.series;
|
7378 | }
|
7379 | });
|
7380 | this.activeEntries = [...items];
|
7381 | this.activate.emit({ value: item, entries: this.activeEntries });
|
7382 | }
|
7383 | onDeactivate(event, group, fromLegend = false) {
|
7384 | const item = Object.assign({}, event);
|
7385 | if (group) {
|
7386 | item.series = group.name;
|
7387 | }
|
7388 | this.activeEntries = this.activeEntries.filter(i => {
|
7389 | if (fromLegend) {
|
7390 | return i.label !== item.name;
|
7391 | }
|
7392 | else {
|
7393 | return !(i.name === item.name && i.series === item.series);
|
7394 | }
|
7395 | });
|
7396 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
7397 | }
|
7398 | }
|
7399 | BarVertical2DComponent.decorators = [
|
7400 | { type: Component, args: [{
|
7401 | selector: 'ngx-charts-bar-vertical-2d',
|
7402 | template: `
|
7403 | <ngx-charts-chart
|
7404 | [view]="[width, height]"
|
7405 | [showLegend]="legend"
|
7406 | [legendOptions]="legendOptions"
|
7407 | [activeEntries]="activeEntries"
|
7408 | [animations]="animations"
|
7409 | (legendLabelActivate)="onActivate($event, undefined, true)"
|
7410 | (legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
7411 | (legendLabelClick)="onClick($event)"
|
7412 | >
|
7413 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
7414 | <svg:g
|
7415 | ngx-charts-grid-panel-series
|
7416 | [xScale]="groupScale"
|
7417 | [yScale]="valueScale"
|
7418 | [data]="results"
|
7419 | [dims]="dims"
|
7420 | [orient]="barOrientation.Vertical"
|
7421 | ></svg:g>
|
7422 | <svg:g
|
7423 | ngx-charts-x-axis
|
7424 | *ngIf="xAxis"
|
7425 | [xScale]="groupScale"
|
7426 | [dims]="dims"
|
7427 | [showLabel]="showXAxisLabel"
|
7428 | [labelText]="xAxisLabel"
|
7429 | [trimTicks]="trimXAxisTicks"
|
7430 | [rotateTicks]="rotateXAxisTicks"
|
7431 | [maxTickLength]="maxXAxisTickLength"
|
7432 | [tickFormatting]="xAxisTickFormatting"
|
7433 | [ticks]="xAxisTicks"
|
7434 | [xAxisOffset]="dataLabelMaxHeight.negative"
|
7435 | (dimensionsChanged)="updateXAxisHeight($event)"
|
7436 | ></svg:g>
|
7437 | <svg:g
|
7438 | ngx-charts-y-axis
|
7439 | *ngIf="yAxis"
|
7440 | [yScale]="valueScale"
|
7441 | [dims]="dims"
|
7442 | [showGridLines]="showGridLines"
|
7443 | [showLabel]="showYAxisLabel"
|
7444 | [labelText]="yAxisLabel"
|
7445 | [trimTicks]="trimYAxisTicks"
|
7446 | [maxTickLength]="maxYAxisTickLength"
|
7447 | [tickFormatting]="yAxisTickFormatting"
|
7448 | [ticks]="yAxisTicks"
|
7449 | (dimensionsChanged)="updateYAxisWidth($event)"
|
7450 | ></svg:g>
|
7451 | <svg:g
|
7452 | ngx-charts-series-vertical
|
7453 | *ngFor="let group of results; let index = index; trackBy: trackBy"
|
7454 | [@animationState]="'active'"
|
7455 | [attr.transform]="groupTransform(group)"
|
7456 | [activeEntries]="activeEntries"
|
7457 | [xScale]="innerScale"
|
7458 | [yScale]="valueScale"
|
7459 | [colors]="colors"
|
7460 | [series]="group.series"
|
7461 | [dims]="dims"
|
7462 | [gradient]="gradient"
|
7463 | [tooltipDisabled]="tooltipDisabled"
|
7464 | [tooltipTemplate]="tooltipTemplate"
|
7465 | [showDataLabel]="showDataLabel"
|
7466 | [dataLabelFormatting]="dataLabelFormatting"
|
7467 | [seriesName]="group.name"
|
7468 | [roundEdges]="roundEdges"
|
7469 | [animations]="animations"
|
7470 | [noBarWhenZero]="noBarWhenZero"
|
7471 | (select)="onClick($event, group)"
|
7472 | (activate)="onActivate($event, group)"
|
7473 | (deactivate)="onDeactivate($event, group)"
|
7474 | (dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
7475 | />
|
7476 | </svg:g>
|
7477 | </ngx-charts-chart>
|
7478 | `,
|
7479 | encapsulation: ViewEncapsulation.None,
|
7480 | changeDetection: ChangeDetectionStrategy.OnPush,
|
7481 | animations: [
|
7482 | trigger('animationState', [
|
7483 | transition(':leave', [
|
7484 | style({
|
7485 | opacity: 1,
|
7486 | transform: '*'
|
7487 | }),
|
7488 | animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
7489 | ])
|
7490 | ])
|
7491 | ],
|
7492 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
7493 | },] }
|
7494 | ];
|
7495 | BarVertical2DComponent.propDecorators = {
|
7496 | legend: [{ type: Input }],
|
7497 | legendTitle: [{ type: Input }],
|
7498 | legendPosition: [{ type: Input }],
|
7499 | xAxis: [{ type: Input }],
|
7500 | yAxis: [{ type: Input }],
|
7501 | showXAxisLabel: [{ type: Input }],
|
7502 | showYAxisLabel: [{ type: Input }],
|
7503 | xAxisLabel: [{ type: Input }],
|
7504 | yAxisLabel: [{ type: Input }],
|
7505 | tooltipDisabled: [{ type: Input }],
|
7506 | scaleType: [{ type: Input }],
|
7507 | gradient: [{ type: Input }],
|
7508 | showGridLines: [{ type: Input }],
|
7509 | activeEntries: [{ type: Input }],
|
7510 | schemeType: [{ type: Input }],
|
7511 | trimXAxisTicks: [{ type: Input }],
|
7512 | trimYAxisTicks: [{ type: Input }],
|
7513 | rotateXAxisTicks: [{ type: Input }],
|
7514 | maxXAxisTickLength: [{ type: Input }],
|
7515 | maxYAxisTickLength: [{ type: Input }],
|
7516 | xAxisTickFormatting: [{ type: Input }],
|
7517 | yAxisTickFormatting: [{ type: Input }],
|
7518 | xAxisTicks: [{ type: Input }],
|
7519 | yAxisTicks: [{ type: Input }],
|
7520 | groupPadding: [{ type: Input }],
|
7521 | barPadding: [{ type: Input }],
|
7522 | roundDomains: [{ type: Input }],
|
7523 | roundEdges: [{ type: Input }],
|
7524 | yScaleMax: [{ type: Input }],
|
7525 | showDataLabel: [{ type: Input }],
|
7526 | dataLabelFormatting: [{ type: Input }],
|
7527 | noBarWhenZero: [{ type: Input }],
|
7528 | activate: [{ type: Output }],
|
7529 | deactivate: [{ type: Output }],
|
7530 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
7531 | };
|
7532 |
|
7533 | class BarVerticalNormalizedComponent extends BaseChartComponent {
|
7534 | constructor() {
|
7535 | super(...arguments);
|
7536 | this.legend = false;
|
7537 | this.legendTitle = 'Legend';
|
7538 | this.legendPosition = LegendPosition.Right;
|
7539 | this.tooltipDisabled = false;
|
7540 | this.showGridLines = true;
|
7541 | this.activeEntries = [];
|
7542 | this.trimXAxisTicks = true;
|
7543 | this.trimYAxisTicks = true;
|
7544 | this.rotateXAxisTicks = true;
|
7545 | this.maxXAxisTickLength = 16;
|
7546 | this.maxYAxisTickLength = 16;
|
7547 | this.barPadding = 8;
|
7548 | this.roundDomains = false;
|
7549 | this.noBarWhenZero = true;
|
7550 | this.activate = new EventEmitter();
|
7551 | this.deactivate = new EventEmitter();
|
7552 | this.valueDomain = [0, 100];
|
7553 | this.margin = [10, 20, 10, 20];
|
7554 | this.xAxisHeight = 0;
|
7555 | this.yAxisWidth = 0;
|
7556 | this.barChartType = BarChartType;
|
7557 | this.trackBy = (index, item) => {
|
7558 | return item.name;
|
7559 | };
|
7560 | }
|
7561 | update() {
|
7562 | super.update();
|
7563 | this.dims = calculateViewDimensions({
|
7564 | width: this.width,
|
7565 | height: this.height,
|
7566 | margins: this.margin,
|
7567 | showXAxis: this.xAxis,
|
7568 | showYAxis: this.yAxis,
|
7569 | xAxisHeight: this.xAxisHeight,
|
7570 | yAxisWidth: this.yAxisWidth,
|
7571 | showXLabel: this.showXAxisLabel,
|
7572 | showYLabel: this.showYAxisLabel,
|
7573 | showLegend: this.legend,
|
7574 | legendType: this.schemeType,
|
7575 | legendPosition: this.legendPosition
|
7576 | });
|
7577 | this.formatDates();
|
7578 | this.groupDomain = this.getGroupDomain();
|
7579 | this.innerDomain = this.getInnerDomain();
|
7580 | this.xScale = this.getXScale();
|
7581 | this.yScale = this.getYScale();
|
7582 | this.setColors();
|
7583 | this.legendOptions = this.getLegendOptions();
|
7584 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
7585 | }
|
7586 | getGroupDomain() {
|
7587 | const domain = [];
|
7588 | for (const group of this.results) {
|
7589 | if (!domain.includes(group.label)) {
|
7590 | domain.push(group.label);
|
7591 | }
|
7592 | }
|
7593 | return domain;
|
7594 | }
|
7595 | getInnerDomain() {
|
7596 | const domain = [];
|
7597 | for (const group of this.results) {
|
7598 | for (const d of group.series) {
|
7599 | if (!domain.includes(d.label)) {
|
7600 | domain.push(d.label);
|
7601 | }
|
7602 | }
|
7603 | }
|
7604 | return domain;
|
7605 | }
|
7606 | getXScale() {
|
7607 | const spacing = this.groupDomain.length / (this.dims.width / this.barPadding + 1);
|
7608 | return scaleBand().rangeRound([0, this.dims.width]).paddingInner(spacing).domain(this.groupDomain);
|
7609 | }
|
7610 | getYScale() {
|
7611 | const scale = scaleLinear().range([this.dims.height, 0]).domain(this.valueDomain);
|
7612 | return this.roundDomains ? scale.nice() : scale;
|
7613 | }
|
7614 | groupTransform(group) {
|
7615 | return `translate(${this.xScale(group.name)}, 0)`;
|
7616 | }
|
7617 | onClick(data, group) {
|
7618 | if (group) {
|
7619 | data.series = group.name;
|
7620 | }
|
7621 | this.select.emit(data);
|
7622 | }
|
7623 | setColors() {
|
7624 | let domain;
|
7625 | if (this.schemeType === ScaleType.Ordinal) {
|
7626 | domain = this.innerDomain;
|
7627 | }
|
7628 | else {
|
7629 | domain = this.valueDomain;
|
7630 | }
|
7631 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
7632 | }
|
7633 | getLegendOptions() {
|
7634 | const opts = {
|
7635 | scaleType: this.schemeType,
|
7636 | colors: undefined,
|
7637 | domain: [],
|
7638 | title: undefined,
|
7639 | position: this.legendPosition
|
7640 | };
|
7641 | if (opts.scaleType === ScaleType.Ordinal) {
|
7642 | opts.domain = this.innerDomain;
|
7643 | opts.colors = this.colors;
|
7644 | opts.title = this.legendTitle;
|
7645 | }
|
7646 | else {
|
7647 | opts.domain = this.valueDomain;
|
7648 | opts.colors = this.colors.scale;
|
7649 | }
|
7650 | return opts;
|
7651 | }
|
7652 | updateYAxisWidth({ width }) {
|
7653 | this.yAxisWidth = width;
|
7654 | this.update();
|
7655 | }
|
7656 | updateXAxisHeight({ height }) {
|
7657 | this.xAxisHeight = height;
|
7658 | this.update();
|
7659 | }
|
7660 | onActivate(event, group, fromLegend = false) {
|
7661 | const item = Object.assign({}, event);
|
7662 | if (group) {
|
7663 | item.series = group.name;
|
7664 | }
|
7665 | const items = this.results
|
7666 | .map(g => g.series)
|
7667 | .flat()
|
7668 | .filter(i => {
|
7669 | if (fromLegend) {
|
7670 | return i.label === item.name;
|
7671 | }
|
7672 | else {
|
7673 | return i.name === item.name && i.series === item.series;
|
7674 | }
|
7675 | });
|
7676 | this.activeEntries = [...items];
|
7677 | this.activate.emit({ value: item, entries: this.activeEntries });
|
7678 | }
|
7679 | onDeactivate(event, group, fromLegend = false) {
|
7680 | const item = Object.assign({}, event);
|
7681 | if (group) {
|
7682 | item.series = group.name;
|
7683 | }
|
7684 | this.activeEntries = this.activeEntries.filter(i => {
|
7685 | if (fromLegend) {
|
7686 | return i.label !== item.name;
|
7687 | }
|
7688 | else {
|
7689 | return !(i.name === item.name && i.series === item.series);
|
7690 | }
|
7691 | });
|
7692 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
7693 | }
|
7694 | }
|
7695 | BarVerticalNormalizedComponent.decorators = [
|
7696 | { type: Component, args: [{
|
7697 | selector: 'ngx-charts-bar-vertical-normalized',
|
7698 | template: `
|
7699 | <ngx-charts-chart
|
7700 | [view]="[width, height]"
|
7701 | [showLegend]="legend"
|
7702 | [legendOptions]="legendOptions"
|
7703 | [activeEntries]="activeEntries"
|
7704 | [animations]="animations"
|
7705 | (legendLabelActivate)="onActivate($event, undefined, true)"
|
7706 | (legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
7707 | (legendLabelClick)="onClick($event)"
|
7708 | >
|
7709 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
7710 | <svg:g
|
7711 | ngx-charts-x-axis
|
7712 | *ngIf="xAxis"
|
7713 | [xScale]="xScale"
|
7714 | [dims]="dims"
|
7715 | [showLabel]="showXAxisLabel"
|
7716 | [labelText]="xAxisLabel"
|
7717 | [trimTicks]="trimXAxisTicks"
|
7718 | [rotateTicks]="rotateXAxisTicks"
|
7719 | [maxTickLength]="maxXAxisTickLength"
|
7720 | [tickFormatting]="xAxisTickFormatting"
|
7721 | [ticks]="xAxisTicks"
|
7722 | (dimensionsChanged)="updateXAxisHeight($event)"
|
7723 | ></svg:g>
|
7724 | <svg:g
|
7725 | ngx-charts-y-axis
|
7726 | *ngIf="yAxis"
|
7727 | [yScale]="yScale"
|
7728 | [dims]="dims"
|
7729 | [showGridLines]="showGridLines"
|
7730 | [showLabel]="showYAxisLabel"
|
7731 | [labelText]="yAxisLabel"
|
7732 | [trimTicks]="trimYAxisTicks"
|
7733 | [maxTickLength]="maxYAxisTickLength"
|
7734 | [tickFormatting]="yAxisTickFormatting"
|
7735 | [ticks]="yAxisTicks"
|
7736 | (dimensionsChanged)="updateYAxisWidth($event)"
|
7737 | ></svg:g>
|
7738 | <svg:g
|
7739 | *ngFor="let group of results; trackBy: trackBy"
|
7740 | [@animationState]="'active'"
|
7741 | [attr.transform]="groupTransform(group)"
|
7742 | >
|
7743 | <svg:g
|
7744 | ngx-charts-series-vertical
|
7745 | [type]="barChartType.Normalized"
|
7746 | [xScale]="xScale"
|
7747 | [yScale]="yScale"
|
7748 | [activeEntries]="activeEntries"
|
7749 | [colors]="colors"
|
7750 | [series]="group.series"
|
7751 | [dims]="dims"
|
7752 | [gradient]="gradient"
|
7753 | [tooltipDisabled]="tooltipDisabled"
|
7754 | [tooltipTemplate]="tooltipTemplate"
|
7755 | [seriesName]="group.name"
|
7756 | [animations]="animations"
|
7757 | [noBarWhenZero]="noBarWhenZero"
|
7758 | (select)="onClick($event, group)"
|
7759 | (activate)="onActivate($event, group)"
|
7760 | (deactivate)="onDeactivate($event, group)"
|
7761 | />
|
7762 | </svg:g>
|
7763 | </svg:g>
|
7764 | </ngx-charts-chart>
|
7765 | `,
|
7766 | encapsulation: ViewEncapsulation.None,
|
7767 | changeDetection: ChangeDetectionStrategy.OnPush,
|
7768 | animations: [
|
7769 | trigger('animationState', [
|
7770 | transition(':leave', [
|
7771 | style({
|
7772 | opacity: 1,
|
7773 | transform: '*'
|
7774 | }),
|
7775 | animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
7776 | ])
|
7777 | ])
|
7778 | ],
|
7779 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
7780 | },] }
|
7781 | ];
|
7782 | BarVerticalNormalizedComponent.propDecorators = {
|
7783 | legend: [{ type: Input }],
|
7784 | legendTitle: [{ type: Input }],
|
7785 | legendPosition: [{ type: Input }],
|
7786 | xAxis: [{ type: Input }],
|
7787 | yAxis: [{ type: Input }],
|
7788 | showXAxisLabel: [{ type: Input }],
|
7789 | showYAxisLabel: [{ type: Input }],
|
7790 | xAxisLabel: [{ type: Input }],
|
7791 | yAxisLabel: [{ type: Input }],
|
7792 | tooltipDisabled: [{ type: Input }],
|
7793 | gradient: [{ type: Input }],
|
7794 | showGridLines: [{ type: Input }],
|
7795 | activeEntries: [{ type: Input }],
|
7796 | schemeType: [{ type: Input }],
|
7797 | trimXAxisTicks: [{ type: Input }],
|
7798 | trimYAxisTicks: [{ type: Input }],
|
7799 | rotateXAxisTicks: [{ type: Input }],
|
7800 | maxXAxisTickLength: [{ type: Input }],
|
7801 | maxYAxisTickLength: [{ type: Input }],
|
7802 | xAxisTickFormatting: [{ type: Input }],
|
7803 | yAxisTickFormatting: [{ type: Input }],
|
7804 | xAxisTicks: [{ type: Input }],
|
7805 | yAxisTicks: [{ type: Input }],
|
7806 | barPadding: [{ type: Input }],
|
7807 | roundDomains: [{ type: Input }],
|
7808 | noBarWhenZero: [{ type: Input }],
|
7809 | activate: [{ type: Output }],
|
7810 | deactivate: [{ type: Output }],
|
7811 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
7812 | };
|
7813 |
|
7814 | class BarVerticalStackedComponent extends BaseChartComponent {
|
7815 | constructor() {
|
7816 | super(...arguments);
|
7817 | this.legend = false;
|
7818 | this.legendTitle = 'Legend';
|
7819 | this.legendPosition = LegendPosition.Right;
|
7820 | this.tooltipDisabled = false;
|
7821 | this.showGridLines = true;
|
7822 | this.activeEntries = [];
|
7823 | this.trimXAxisTicks = true;
|
7824 | this.trimYAxisTicks = true;
|
7825 | this.rotateXAxisTicks = true;
|
7826 | this.maxXAxisTickLength = 16;
|
7827 | this.maxYAxisTickLength = 16;
|
7828 | this.barPadding = 8;
|
7829 | this.roundDomains = false;
|
7830 | this.showDataLabel = false;
|
7831 | this.noBarWhenZero = true;
|
7832 | this.activate = new EventEmitter();
|
7833 | this.deactivate = new EventEmitter();
|
7834 | this.margin = [10, 20, 10, 20];
|
7835 | this.xAxisHeight = 0;
|
7836 | this.yAxisWidth = 0;
|
7837 | this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
7838 | this.barChartType = BarChartType;
|
7839 | this.trackBy = (index, item) => {
|
7840 | return item.name;
|
7841 | };
|
7842 | }
|
7843 | update() {
|
7844 | super.update();
|
7845 | if (!this.showDataLabel) {
|
7846 | this.dataLabelMaxHeight = { negative: 0, positive: 0 };
|
7847 | }
|
7848 | this.margin = [10 + this.dataLabelMaxHeight.positive, 20, 10 + this.dataLabelMaxHeight.negative, 20];
|
7849 | this.dims = calculateViewDimensions({
|
7850 | width: this.width,
|
7851 | height: this.height,
|
7852 | margins: this.margin,
|
7853 | showXAxis: this.xAxis,
|
7854 | showYAxis: this.yAxis,
|
7855 | xAxisHeight: this.xAxisHeight,
|
7856 | yAxisWidth: this.yAxisWidth,
|
7857 | showXLabel: this.showXAxisLabel,
|
7858 | showYLabel: this.showYAxisLabel,
|
7859 | showLegend: this.legend,
|
7860 | legendType: this.schemeType,
|
7861 | legendPosition: this.legendPosition
|
7862 | });
|
7863 | if (this.showDataLabel) {
|
7864 | this.dims.height -= this.dataLabelMaxHeight.negative;
|
7865 | }
|
7866 | this.formatDates();
|
7867 | this.groupDomain = this.getGroupDomain();
|
7868 | this.innerDomain = this.getInnerDomain();
|
7869 | this.valueDomain = this.getValueDomain();
|
7870 | this.xScale = this.getXScale();
|
7871 | this.yScale = this.getYScale();
|
7872 | this.setColors();
|
7873 | this.legendOptions = this.getLegendOptions();
|
7874 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0] + this.dataLabelMaxHeight.negative})`;
|
7875 | }
|
7876 | getGroupDomain() {
|
7877 | const domain = [];
|
7878 | for (const group of this.results) {
|
7879 | if (!domain.includes(group.label)) {
|
7880 | domain.push(group.label);
|
7881 | }
|
7882 | }
|
7883 | return domain;
|
7884 | }
|
7885 | getInnerDomain() {
|
7886 | const domain = [];
|
7887 | for (const group of this.results) {
|
7888 | for (const d of group.series) {
|
7889 | if (!domain.includes(d.label)) {
|
7890 | domain.push(d.label);
|
7891 | }
|
7892 | }
|
7893 | }
|
7894 | return domain;
|
7895 | }
|
7896 | getValueDomain() {
|
7897 | const domain = [];
|
7898 | let smallest = 0;
|
7899 | let biggest = 0;
|
7900 | for (const group of this.results) {
|
7901 | let smallestSum = 0;
|
7902 | let biggestSum = 0;
|
7903 | for (const d of group.series) {
|
7904 | if (d.value < 0) {
|
7905 | smallestSum += d.value;
|
7906 | }
|
7907 | else {
|
7908 | biggestSum += d.value;
|
7909 | }
|
7910 | smallest = d.value < smallest ? d.value : smallest;
|
7911 | biggest = d.value > biggest ? d.value : biggest;
|
7912 | }
|
7913 | domain.push(smallestSum);
|
7914 | domain.push(biggestSum);
|
7915 | }
|
7916 | domain.push(smallest);
|
7917 | domain.push(biggest);
|
7918 | const min = Math.min(0, ...domain);
|
7919 | const max = this.yScaleMax ? Math.max(this.yScaleMax, ...domain) : Math.max(...domain);
|
7920 | return [min, max];
|
7921 | }
|
7922 | getXScale() {
|
7923 | const spacing = this.groupDomain.length / (this.dims.width / this.barPadding + 1);
|
7924 | return scaleBand().rangeRound([0, this.dims.width]).paddingInner(spacing).domain(this.groupDomain);
|
7925 | }
|
7926 | getYScale() {
|
7927 | const scale = scaleLinear().range([this.dims.height, 0]).domain(this.valueDomain);
|
7928 | return this.roundDomains ? scale.nice() : scale;
|
7929 | }
|
7930 | onDataLabelMaxHeightChanged(event, groupIndex) {
|
7931 | if (event.size.negative) {
|
7932 | this.dataLabelMaxHeight.negative = Math.max(this.dataLabelMaxHeight.negative, event.size.height);
|
7933 | }
|
7934 | else {
|
7935 | this.dataLabelMaxHeight.positive = Math.max(this.dataLabelMaxHeight.positive, event.size.height);
|
7936 | }
|
7937 | if (groupIndex === this.results.length - 1) {
|
7938 | setTimeout(() => this.update());
|
7939 | }
|
7940 | }
|
7941 | groupTransform(group) {
|
7942 | return `translate(${this.xScale(group.name) || 0}, 0)`;
|
7943 | }
|
7944 | onClick(data, group) {
|
7945 | if (group) {
|
7946 | data.series = group.name;
|
7947 | }
|
7948 | this.select.emit(data);
|
7949 | }
|
7950 | setColors() {
|
7951 | let domain;
|
7952 | if (this.schemeType === ScaleType.Ordinal) {
|
7953 | domain = this.innerDomain;
|
7954 | }
|
7955 | else {
|
7956 | domain = this.valueDomain;
|
7957 | }
|
7958 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
7959 | }
|
7960 | getLegendOptions() {
|
7961 | const opts = {
|
7962 | scaleType: this.schemeType,
|
7963 | colors: undefined,
|
7964 | domain: [],
|
7965 | title: undefined,
|
7966 | position: this.legendPosition
|
7967 | };
|
7968 | if (opts.scaleType === ScaleType.Ordinal) {
|
7969 | opts.domain = this.innerDomain;
|
7970 | opts.colors = this.colors;
|
7971 | opts.title = this.legendTitle;
|
7972 | }
|
7973 | else {
|
7974 | opts.domain = this.valueDomain;
|
7975 | opts.colors = this.colors.scale;
|
7976 | }
|
7977 | return opts;
|
7978 | }
|
7979 | updateYAxisWidth({ width }) {
|
7980 | this.yAxisWidth = width;
|
7981 | this.update();
|
7982 | }
|
7983 | updateXAxisHeight({ height }) {
|
7984 | this.xAxisHeight = height;
|
7985 | this.update();
|
7986 | }
|
7987 | onActivate(event, group, fromLegend = false) {
|
7988 | const item = Object.assign({}, event);
|
7989 | if (group) {
|
7990 | item.series = group.name;
|
7991 | }
|
7992 | const items = this.results
|
7993 | .map(g => g.series)
|
7994 | .flat()
|
7995 | .filter(i => {
|
7996 | if (fromLegend) {
|
7997 | return i.label === item.name;
|
7998 | }
|
7999 | else {
|
8000 | return i.name === item.name && i.series === item.series;
|
8001 | }
|
8002 | });
|
8003 | this.activeEntries = [...items];
|
8004 | this.activate.emit({ value: item, entries: this.activeEntries });
|
8005 | }
|
8006 | onDeactivate(event, group, fromLegend = false) {
|
8007 | const item = Object.assign({}, event);
|
8008 | if (group) {
|
8009 | item.series = group.name;
|
8010 | }
|
8011 | this.activeEntries = this.activeEntries.filter(i => {
|
8012 | if (fromLegend) {
|
8013 | return i.label !== item.name;
|
8014 | }
|
8015 | else {
|
8016 | return !(i.name === item.name && i.series === item.series);
|
8017 | }
|
8018 | });
|
8019 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
8020 | }
|
8021 | }
|
8022 | BarVerticalStackedComponent.decorators = [
|
8023 | { type: Component, args: [{
|
8024 | selector: 'ngx-charts-bar-vertical-stacked',
|
8025 | template: `
|
8026 | <ngx-charts-chart
|
8027 | [view]="[width, height]"
|
8028 | [showLegend]="legend"
|
8029 | [legendOptions]="legendOptions"
|
8030 | [activeEntries]="activeEntries"
|
8031 | [animations]="animations"
|
8032 | (legendLabelActivate)="onActivate($event, undefined, true)"
|
8033 | (legendLabelDeactivate)="onDeactivate($event, undefined, true)"
|
8034 | (legendLabelClick)="onClick($event)"
|
8035 | >
|
8036 | <svg:g [attr.transform]="transform" class="bar-chart chart">
|
8037 | <svg:g
|
8038 | ngx-charts-x-axis
|
8039 | *ngIf="xAxis"
|
8040 | [xScale]="xScale"
|
8041 | [dims]="dims"
|
8042 | [showLabel]="showXAxisLabel"
|
8043 | [labelText]="xAxisLabel"
|
8044 | [trimTicks]="trimXAxisTicks"
|
8045 | [rotateTicks]="rotateXAxisTicks"
|
8046 | [maxTickLength]="maxXAxisTickLength"
|
8047 | [tickFormatting]="xAxisTickFormatting"
|
8048 | [ticks]="xAxisTicks"
|
8049 | [xAxisOffset]="dataLabelMaxHeight.negative"
|
8050 | (dimensionsChanged)="updateXAxisHeight($event)"
|
8051 | ></svg:g>
|
8052 | <svg:g
|
8053 | ngx-charts-y-axis
|
8054 | *ngIf="yAxis"
|
8055 | [yScale]="yScale"
|
8056 | [dims]="dims"
|
8057 | [showGridLines]="showGridLines"
|
8058 | [showLabel]="showYAxisLabel"
|
8059 | [labelText]="yAxisLabel"
|
8060 | [trimTicks]="trimYAxisTicks"
|
8061 | [maxTickLength]="maxYAxisTickLength"
|
8062 | [tickFormatting]="yAxisTickFormatting"
|
8063 | [ticks]="yAxisTicks"
|
8064 | (dimensionsChanged)="updateYAxisWidth($event)"
|
8065 | ></svg:g>
|
8066 | <svg:g
|
8067 | *ngFor="let group of results; let index = index; trackBy: trackBy"
|
8068 | [@animationState]="'active'"
|
8069 | [attr.transform]="groupTransform(group)"
|
8070 | >
|
8071 | <svg:g
|
8072 | ngx-charts-series-vertical
|
8073 | [type]="barChartType.Stacked"
|
8074 | [xScale]="xScale"
|
8075 | [yScale]="yScale"
|
8076 | [activeEntries]="activeEntries"
|
8077 | [colors]="colors"
|
8078 | [series]="group.series"
|
8079 | [dims]="dims"
|
8080 | [gradient]="gradient"
|
8081 | [tooltipDisabled]="tooltipDisabled"
|
8082 | [tooltipTemplate]="tooltipTemplate"
|
8083 | [showDataLabel]="showDataLabel"
|
8084 | [dataLabelFormatting]="dataLabelFormatting"
|
8085 | [seriesName]="group.name"
|
8086 | [animations]="animations"
|
8087 | [noBarWhenZero]="noBarWhenZero"
|
8088 | (select)="onClick($event, group)"
|
8089 | (activate)="onActivate($event, group)"
|
8090 | (deactivate)="onDeactivate($event, group)"
|
8091 | (dataLabelHeightChanged)="onDataLabelMaxHeightChanged($event, index)"
|
8092 | />
|
8093 | </svg:g>
|
8094 | </svg:g>
|
8095 | </ngx-charts-chart>
|
8096 | `,
|
8097 | encapsulation: ViewEncapsulation.None,
|
8098 | changeDetection: ChangeDetectionStrategy.OnPush,
|
8099 | animations: [
|
8100 | trigger('animationState', [
|
8101 | transition(':leave', [
|
8102 | style({
|
8103 | opacity: 1,
|
8104 | transform: '*'
|
8105 | }),
|
8106 | animate(500, style({ opacity: 0, transform: 'scale(0)' }))
|
8107 | ])
|
8108 | ])
|
8109 | ],
|
8110 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
8111 | },] }
|
8112 | ];
|
8113 | BarVerticalStackedComponent.propDecorators = {
|
8114 | legend: [{ type: Input }],
|
8115 | legendTitle: [{ type: Input }],
|
8116 | legendPosition: [{ type: Input }],
|
8117 | xAxis: [{ type: Input }],
|
8118 | yAxis: [{ type: Input }],
|
8119 | showXAxisLabel: [{ type: Input }],
|
8120 | showYAxisLabel: [{ type: Input }],
|
8121 | xAxisLabel: [{ type: Input }],
|
8122 | yAxisLabel: [{ type: Input }],
|
8123 | tooltipDisabled: [{ type: Input }],
|
8124 | gradient: [{ type: Input }],
|
8125 | showGridLines: [{ type: Input }],
|
8126 | activeEntries: [{ type: Input }],
|
8127 | schemeType: [{ type: Input }],
|
8128 | trimXAxisTicks: [{ type: Input }],
|
8129 | trimYAxisTicks: [{ type: Input }],
|
8130 | rotateXAxisTicks: [{ type: Input }],
|
8131 | maxXAxisTickLength: [{ type: Input }],
|
8132 | maxYAxisTickLength: [{ type: Input }],
|
8133 | xAxisTickFormatting: [{ type: Input }],
|
8134 | yAxisTickFormatting: [{ type: Input }],
|
8135 | xAxisTicks: [{ type: Input }],
|
8136 | yAxisTicks: [{ type: Input }],
|
8137 | barPadding: [{ type: Input }],
|
8138 | roundDomains: [{ type: Input }],
|
8139 | yScaleMax: [{ type: Input }],
|
8140 | showDataLabel: [{ type: Input }],
|
8141 | dataLabelFormatting: [{ type: Input }],
|
8142 | noBarWhenZero: [{ type: Input }],
|
8143 | activate: [{ type: Output }],
|
8144 | deactivate: [{ type: Output }],
|
8145 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
8146 | };
|
8147 |
|
8148 | var D0Types;
|
8149 | (function (D0Types) {
|
8150 | D0Types["positive"] = "positive";
|
8151 | D0Types["negative"] = "negative";
|
8152 | })(D0Types || (D0Types = {}));
|
8153 |
|
8154 | class SeriesHorizontal {
|
8155 | constructor() {
|
8156 | this.type = BarChartType.Standard;
|
8157 | this.tooltipDisabled = false;
|
8158 | this.animations = true;
|
8159 | this.showDataLabel = false;
|
8160 | this.noBarWhenZero = true;
|
8161 | this.select = new EventEmitter();
|
8162 | this.activate = new EventEmitter();
|
8163 | this.deactivate = new EventEmitter();
|
8164 | this.dataLabelWidthChanged = new EventEmitter();
|
8165 | this.barsForDataLabels = [];
|
8166 | this.barOrientation = BarOrientation;
|
8167 | }
|
8168 | ngOnChanges(changes) {
|
8169 | this.update();
|
8170 | }
|
8171 | update() {
|
8172 | this.updateTooltipSettings();
|
8173 | const d0 = {
|
8174 | [D0Types.positive]: 0,
|
8175 | [D0Types.negative]: 0
|
8176 | };
|
8177 | let d0Type;
|
8178 | d0Type = D0Types.positive;
|
8179 | let total;
|
8180 | if (this.type === BarChartType.Normalized) {
|
8181 | total = this.series.map(d => d.value).reduce((sum, d) => sum + d, 0);
|
8182 | }
|
8183 | const xScaleMin = Math.max(this.xScale.domain()[0], 0);
|
8184 | this.bars = this.series.map(d => {
|
8185 | let value = d.value;
|
8186 | const label = this.getLabel(d);
|
8187 | const formattedLabel = formatLabel(label);
|
8188 | const roundEdges = this.roundEdges;
|
8189 | d0Type = value > 0 ? D0Types.positive : D0Types.negative;
|
8190 | const bar = {
|
8191 | value,
|
8192 | label,
|
8193 | roundEdges,
|
8194 | data: d,
|
8195 | formattedLabel
|
8196 | };
|
8197 | bar.height = this.yScale.bandwidth();
|
8198 | if (this.type === BarChartType.Standard) {
|
8199 | bar.width = Math.abs(this.xScale(value) - this.xScale(xScaleMin));
|
8200 | if (value < 0) {
|
8201 | bar.x = this.xScale(value);
|
8202 | }
|
8203 | else {
|
8204 | bar.x = this.xScale(xScaleMin);
|
8205 | }
|
8206 | bar.y = this.yScale(label);
|
8207 | }
|
8208 | else if (this.type === BarChartType.Stacked) {
|
8209 | const offset0 = d0[d0Type];
|
8210 | const offset1 = offset0 + value;
|
8211 | d0[d0Type] += value;
|
8212 | bar.width = this.xScale(offset1) - this.xScale(offset0);
|
8213 | bar.x = this.xScale(offset0);
|
8214 | bar.y = 0;
|
8215 | bar.offset0 = offset0;
|
8216 | bar.offset1 = offset1;
|
8217 | }
|
8218 | else if (this.type === BarChartType.Normalized) {
|
8219 | let offset0 = d0[d0Type];
|
8220 | let offset1 = offset0 + value;
|
8221 | d0[d0Type] += value;
|
8222 | if (total > 0) {
|
8223 | offset0 = (offset0 * 100) / total;
|
8224 | offset1 = (offset1 * 100) / total;
|
8225 | }
|
8226 | else {
|
8227 | offset0 = 0;
|
8228 | offset1 = 0;
|
8229 | }
|
8230 | bar.width = this.xScale(offset1) - this.xScale(offset0);
|
8231 | bar.x = this.xScale(offset0);
|
8232 | bar.y = 0;
|
8233 | bar.offset0 = offset0;
|
8234 | bar.offset1 = offset1;
|
8235 | value = (offset1 - offset0).toFixed(2) + '%';
|
8236 | }
|
8237 | if (this.colors.scaleType === ScaleType.Ordinal) {
|
8238 | bar.color = this.colors.getColor(label);
|
8239 | }
|
8240 | else {
|
8241 | if (this.type === BarChartType.Standard) {
|
8242 | bar.color = this.colors.getColor(value);
|
8243 | bar.gradientStops = this.colors.getLinearGradientStops(value);
|
8244 | }
|
8245 | else {
|
8246 | bar.color = this.colors.getColor(bar.offset1);
|
8247 | bar.gradientStops = this.colors.getLinearGradientStops(bar.offset1, bar.offset0);
|
8248 | }
|
8249 | }
|
8250 | let tooltipLabel = formattedLabel;
|
8251 | bar.ariaLabel = formattedLabel + ' ' + value.toLocaleString();
|
8252 | if (this.seriesName !== null && this.seriesName !== undefined) {
|
8253 | tooltipLabel = `${this.seriesName} • ${formattedLabel}`;
|
8254 | bar.data.series = this.seriesName;
|
8255 | bar.ariaLabel = this.seriesName + ' ' + bar.ariaLabel;
|
8256 | }
|
8257 | bar.tooltipText = this.tooltipDisabled
|
8258 | ? undefined
|
8259 | : `
|
8260 | <span class="tooltip-label">${escapeLabel(tooltipLabel)}</span>
|
8261 | <span class="tooltip-val">${this.dataLabelFormatting ? this.dataLabelFormatting(value) : value.toLocaleString()}</span>
|
8262 | `;
|
8263 | return bar;
|
8264 | });
|
8265 | this.updateDataLabels();
|
8266 | }
|
8267 | updateDataLabels() {
|
8268 | if (this.type === BarChartType.Stacked) {
|
8269 | this.barsForDataLabels = [];
|
8270 | const section = {};
|
8271 | section.series = this.seriesName;
|
8272 | const totalPositive = this.series.map(d => d.value).reduce((sum, d) => (d > 0 ? sum + d : sum), 0);
|
8273 | const totalNegative = this.series.map(d => d.value).reduce((sum, d) => (d < 0 ? sum + d : sum), 0);
|
8274 | section.total = totalPositive + totalNegative;
|
8275 | section.x = 0;
|
8276 | section.y = 0;
|
8277 |
|
8278 | if (section.total > 0) {
|
8279 | section.width = this.xScale(totalPositive);
|
8280 | }
|
8281 | else {
|
8282 | section.width = this.xScale(totalNegative);
|
8283 | }
|
8284 | section.height = this.yScale.bandwidth();
|
8285 | this.barsForDataLabels.push(section);
|
8286 | }
|
8287 | else {
|
8288 | this.barsForDataLabels = this.series.map(d => {
|
8289 | var _a;
|
8290 | const section = {};
|
8291 | section.series = (_a = this.seriesName) !== null && _a !== void 0 ? _a : d.label;
|
8292 | section.total = d.value;
|
8293 | section.x = this.xScale(0);
|
8294 | section.y = this.yScale(d.label);
|
8295 | section.width = this.xScale(section.total) - this.xScale(0);
|
8296 | section.height = this.yScale.bandwidth();
|
8297 | return section;
|
8298 | });
|
8299 | }
|
8300 | }
|
8301 | updateTooltipSettings() {
|
8302 | this.tooltipPlacement = this.tooltipDisabled ? undefined : PlacementTypes.Top;
|
8303 | this.tooltipType = this.tooltipDisabled ? undefined : StyleTypes.tooltip;
|
8304 | }
|
8305 | isActive(entry) {
|
8306 | if (!this.activeEntries)
|
8307 | return false;
|
8308 | const item = this.activeEntries.find(active => {
|
8309 | return entry.name === active.name && entry.value === active.value;
|
8310 | });
|
8311 | return item !== undefined;
|
8312 | }
|
8313 | getLabel(dataItem) {
|
8314 | if (dataItem.label) {
|
8315 | return dataItem.label;
|
8316 | }
|
8317 | return dataItem.name;
|
8318 | }
|
8319 | trackBy(index, bar) {
|
8320 | return bar.label;
|
8321 | }
|
8322 | trackDataLabelBy(index, barLabel) {
|
8323 | return index + '#' + barLabel.series + '#' + barLabel.total;
|
8324 | }
|
8325 | click(data) {
|
8326 | this.select.emit(data);
|
8327 | }
|
8328 | }
|
8329 | SeriesHorizontal.decorators = [
|
8330 | { type: Component, args: [{
|
8331 | selector: 'g[ngx-charts-series-horizontal]',
|
8332 | template: `
|
8333 | <svg:g
|
8334 | ngx-charts-bar
|
8335 | *ngFor="let bar of bars; trackBy: trackBy"
|
8336 | [@animationState]="'active'"
|
8337 | [width]="bar.width"
|
8338 | [height]="bar.height"
|
8339 | [x]="bar.x"
|
8340 | [y]="bar.y"
|
8341 | [fill]="bar.color"
|
8342 | [stops]="bar.gradientStops"
|
8343 | [data]="bar.data"
|
8344 | [orientation]="barOrientation.Horizontal"
|
8345 | [roundEdges]="bar.roundEdges"
|
8346 | (select)="click($event)"
|
8347 | [gradient]="gradient"
|
8348 | [isActive]="isActive(bar.data)"
|
8349 | [ariaLabel]="bar.ariaLabel"
|
8350 | [animations]="animations"
|
8351 | (activate)="activate.emit($event)"
|
8352 | (deactivate)="deactivate.emit($event)"
|
8353 | ngx-tooltip
|
8354 | [tooltipDisabled]="tooltipDisabled"
|
8355 | [tooltipPlacement]="tooltipPlacement"
|
8356 | [tooltipType]="tooltipType"
|
8357 | [tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
8358 | [tooltipTemplate]="tooltipTemplate"
|
8359 | [tooltipContext]="bar.data"
|
8360 | [noBarWhenZero]="noBarWhenZero"
|
8361 | ></svg:g>
|
8362 | <svg:g *ngIf="showDataLabel">
|
8363 | <svg:g
|
8364 | ngx-charts-bar-label
|
8365 | *ngFor="let b of barsForDataLabels; let i = index; trackBy: trackDataLabelBy"
|
8366 | [barX]="b.x"
|
8367 | [barY]="b.y"
|
8368 | [barWidth]="b.width"
|
8369 | [barHeight]="b.height"
|
8370 | [value]="b.total"
|
8371 | [valueFormatting]="dataLabelFormatting"
|
8372 | [orientation]="barOrientation.Horizontal"
|
8373 | (dimensionsChanged)="dataLabelWidthChanged.emit({ size: $event, index: i })"
|
8374 | />
|
8375 | </svg:g>
|
8376 | `,
|
8377 | changeDetection: ChangeDetectionStrategy.OnPush,
|
8378 | animations: [
|
8379 | trigger('animationState', [
|
8380 | transition(':leave', [
|
8381 | style({
|
8382 | opacity: 1
|
8383 | }),
|
8384 | animate(500, style({ opacity: 0 }))
|
8385 | ])
|
8386 | ])
|
8387 | ]
|
8388 | },] }
|
8389 | ];
|
8390 | SeriesHorizontal.propDecorators = {
|
8391 | dims: [{ type: Input }],
|
8392 | type: [{ type: Input }],
|
8393 | series: [{ type: Input }],
|
8394 | xScale: [{ type: Input }],
|
8395 | yScale: [{ type: Input }],
|
8396 | colors: [{ type: Input }],
|
8397 | tooltipDisabled: [{ type: Input }],
|
8398 | gradient: [{ type: Input }],
|
8399 | activeEntries: [{ type: Input }],
|
8400 | seriesName: [{ type: Input }],
|
8401 | tooltipTemplate: [{ type: Input }],
|
8402 | roundEdges: [{ type: Input }],
|
8403 | animations: [{ type: Input }],
|
8404 | showDataLabel: [{ type: Input }],
|
8405 | dataLabelFormatting: [{ type: Input }],
|
8406 | noBarWhenZero: [{ type: Input }],
|
8407 | select: [{ type: Output }],
|
8408 | activate: [{ type: Output }],
|
8409 | deactivate: [{ type: Output }],
|
8410 | dataLabelWidthChanged: [{ type: Output }]
|
8411 | };
|
8412 |
|
8413 | class SeriesVerticalComponent {
|
8414 | constructor() {
|
8415 | this.type = BarChartType.Standard;
|
8416 | this.tooltipDisabled = false;
|
8417 | this.animations = true;
|
8418 | this.showDataLabel = false;
|
8419 | this.noBarWhenZero = true;
|
8420 | this.select = new EventEmitter();
|
8421 | this.activate = new EventEmitter();
|
8422 | this.deactivate = new EventEmitter();
|
8423 | this.dataLabelHeightChanged = new EventEmitter();
|
8424 | this.barsForDataLabels = [];
|
8425 | this.barOrientation = BarOrientation;
|
8426 | }
|
8427 | ngOnChanges(changes) {
|
8428 | this.update();
|
8429 | }
|
8430 | update() {
|
8431 | this.updateTooltipSettings();
|
8432 | let width;
|
8433 | if (this.series.length) {
|
8434 | width = this.xScale.bandwidth();
|
8435 | }
|
8436 | width = Math.round(width);
|
8437 | const yScaleMin = Math.max(this.yScale.domain()[0], 0);
|
8438 | const d0 = {
|
8439 | [D0Types.positive]: 0,
|
8440 | [D0Types.negative]: 0
|
8441 | };
|
8442 | let d0Type = D0Types.positive;
|
8443 | let total;
|
8444 | if (this.type === BarChartType.Normalized) {
|
8445 | total = this.series.map(d => d.value).reduce((sum, d) => sum + d, 0);
|
8446 | }
|
8447 | this.bars = this.series.map((d, index) => {
|
8448 | let value = d.value;
|
8449 | const label = this.getLabel(d);
|
8450 | const formattedLabel = formatLabel(label);
|
8451 | const roundEdges = this.roundEdges;
|
8452 | d0Type = value > 0 ? D0Types.positive : D0Types.negative;
|
8453 | const bar = {
|
8454 | value,
|
8455 | label,
|
8456 | roundEdges,
|
8457 | data: d,
|
8458 | width,
|
8459 | formattedLabel,
|
8460 | height: 0,
|
8461 | x: 0,
|
8462 | y: 0
|
8463 | };
|
8464 | if (this.type === BarChartType.Standard) {
|
8465 | bar.height = Math.abs(this.yScale(value) - this.yScale(yScaleMin));
|
8466 | bar.x = this.xScale(label);
|
8467 | if (value < 0) {
|
8468 | bar.y = this.yScale(0);
|
8469 | }
|
8470 | else {
|
8471 | bar.y = this.yScale(value);
|
8472 | }
|
8473 | }
|
8474 | else if (this.type === BarChartType.Stacked) {
|
8475 | const offset0 = d0[d0Type];
|
8476 | const offset1 = offset0 + value;
|
8477 | d0[d0Type] += value;
|
8478 | bar.height = this.yScale(offset0) - this.yScale(offset1);
|
8479 | bar.x = 0;
|
8480 | bar.y = this.yScale(offset1);
|
8481 | bar.offset0 = offset0;
|
8482 | bar.offset1 = offset1;
|
8483 | }
|
8484 | else if (this.type === BarChartType.Normalized) {
|
8485 | let offset0 = d0[d0Type];
|
8486 | let offset1 = offset0 + value;
|
8487 | d0[d0Type] += value;
|
8488 | if (total > 0) {
|
8489 | offset0 = (offset0 * 100) / total;
|
8490 | offset1 = (offset1 * 100) / total;
|
8491 | }
|
8492 | else {
|
8493 | offset0 = 0;
|
8494 | offset1 = 0;
|
8495 | }
|
8496 | bar.height = this.yScale(offset0) - this.yScale(offset1);
|
8497 | bar.x = 0;
|
8498 | bar.y = this.yScale(offset1);
|
8499 | bar.offset0 = offset0;
|
8500 | bar.offset1 = offset1;
|
8501 | value = (offset1 - offset0).toFixed(2) + '%';
|
8502 | }
|
8503 | if (this.colors.scaleType === ScaleType.Ordinal) {
|
8504 | bar.color = this.colors.getColor(label);
|
8505 | }
|
8506 | else {
|
8507 | if (this.type === BarChartType.Standard) {
|
8508 | bar.color = this.colors.getColor(value);
|
8509 | bar.gradientStops = this.colors.getLinearGradientStops(value);
|
8510 | }
|
8511 | else {
|
8512 | bar.color = this.colors.getColor(bar.offset1);
|
8513 | bar.gradientStops = this.colors.getLinearGradientStops(bar.offset1, bar.offset0);
|
8514 | }
|
8515 | }
|
8516 | let tooltipLabel = formattedLabel;
|
8517 | bar.ariaLabel = formattedLabel + ' ' + value.toLocaleString();
|
8518 | if (this.seriesName !== null && this.seriesName !== undefined) {
|
8519 | tooltipLabel = `${this.seriesName} • ${formattedLabel}`;
|
8520 | bar.data.series = this.seriesName;
|
8521 | bar.ariaLabel = this.seriesName + ' ' + bar.ariaLabel;
|
8522 | }
|
8523 | bar.tooltipText = this.tooltipDisabled
|
8524 | ? undefined
|
8525 | : `
|
8526 | <span class="tooltip-label">${escapeLabel(tooltipLabel)}</span>
|
8527 | <span class="tooltip-val">${this.dataLabelFormatting ? this.dataLabelFormatting(value) : value.toLocaleString()}</span>
|
8528 | `;
|
8529 | return bar;
|
8530 | });
|
8531 | this.updateDataLabels();
|
8532 | }
|
8533 | updateDataLabels() {
|
8534 | if (this.type === BarChartType.Stacked) {
|
8535 | this.barsForDataLabels = [];
|
8536 | const section = {};
|
8537 | section.series = this.seriesName;
|
8538 | const totalPositive = this.series.map(d => d.value).reduce((sum, d) => (d > 0 ? sum + d : sum), 0);
|
8539 | const totalNegative = this.series.map(d => d.value).reduce((sum, d) => (d < 0 ? sum + d : sum), 0);
|
8540 | section.total = totalPositive + totalNegative;
|
8541 | section.x = 0;
|
8542 | section.y = 0;
|
8543 | if (section.total > 0) {
|
8544 | section.height = this.yScale(totalPositive);
|
8545 | }
|
8546 | else {
|
8547 | section.height = this.yScale(totalNegative);
|
8548 | }
|
8549 | section.width = this.xScale.bandwidth();
|
8550 | this.barsForDataLabels.push(section);
|
8551 | }
|
8552 | else {
|
8553 | this.barsForDataLabels = this.series.map(d => {
|
8554 | var _a;
|
8555 | const section = {};
|
8556 | section.series = (_a = this.seriesName) !== null && _a !== void 0 ? _a : d.label;
|
8557 | section.total = d.value;
|
8558 | section.x = this.xScale(d.label);
|
8559 | section.y = this.yScale(0);
|
8560 | section.height = this.yScale(section.total) - this.yScale(0);
|
8561 | section.width = this.xScale.bandwidth();
|
8562 | return section;
|
8563 | });
|
8564 | }
|
8565 | }
|
8566 | updateTooltipSettings() {
|
8567 | this.tooltipPlacement = this.tooltipDisabled ? undefined : PlacementTypes.Top;
|
8568 | this.tooltipType = this.tooltipDisabled ? undefined : StyleTypes.tooltip;
|
8569 | }
|
8570 | isActive(entry) {
|
8571 | if (!this.activeEntries)
|
8572 | return false;
|
8573 | const item = this.activeEntries.find(active => {
|
8574 | return entry.name === active.name && entry.value === active.value;
|
8575 | });
|
8576 | return item !== undefined;
|
8577 | }
|
8578 | onClick(data) {
|
8579 | this.select.emit(data);
|
8580 | }
|
8581 | getLabel(dataItem) {
|
8582 | if (dataItem.label) {
|
8583 | return dataItem.label;
|
8584 | }
|
8585 | return dataItem.name;
|
8586 | }
|
8587 | trackBy(index, bar) {
|
8588 | return bar.label;
|
8589 | }
|
8590 | trackDataLabelBy(index, barLabel) {
|
8591 | return index + '#' + barLabel.series + '#' + barLabel.total;
|
8592 | }
|
8593 | }
|
8594 | SeriesVerticalComponent.decorators = [
|
8595 | { type: Component, args: [{
|
8596 | selector: 'g[ngx-charts-series-vertical]',
|
8597 | template: `
|
8598 | <svg:g
|
8599 | ngx-charts-bar
|
8600 | *ngFor="let bar of bars; trackBy: trackBy"
|
8601 | [@animationState]="'active'"
|
8602 | [@.disabled]="!animations"
|
8603 | [width]="bar.width"
|
8604 | [height]="bar.height"
|
8605 | [x]="bar.x"
|
8606 | [y]="bar.y"
|
8607 | [fill]="bar.color"
|
8608 | [stops]="bar.gradientStops"
|
8609 | [data]="bar.data"
|
8610 | [orientation]="barOrientation.Vertical"
|
8611 | [roundEdges]="bar.roundEdges"
|
8612 | [gradient]="gradient"
|
8613 | [ariaLabel]="bar.ariaLabel"
|
8614 | [isActive]="isActive(bar.data)"
|
8615 | (select)="onClick($event)"
|
8616 | (activate)="activate.emit($event)"
|
8617 | (deactivate)="deactivate.emit($event)"
|
8618 | ngx-tooltip
|
8619 | [tooltipDisabled]="tooltipDisabled"
|
8620 | [tooltipPlacement]="tooltipPlacement"
|
8621 | [tooltipType]="tooltipType"
|
8622 | [tooltipTitle]="tooltipTemplate ? undefined : bar.tooltipText"
|
8623 | [tooltipTemplate]="tooltipTemplate"
|
8624 | [tooltipContext]="bar.data"
|
8625 | [noBarWhenZero]="noBarWhenZero"
|
8626 | [animations]="animations"
|
8627 | ></svg:g>
|
8628 | <svg:g *ngIf="showDataLabel">
|
8629 | <svg:g
|
8630 | ngx-charts-bar-label
|
8631 | *ngFor="let b of barsForDataLabels; let i = index; trackBy: trackDataLabelBy"
|
8632 | [barX]="b.x"
|
8633 | [barY]="b.y"
|
8634 | [barWidth]="b.width"
|
8635 | [barHeight]="b.height"
|
8636 | [value]="b.total"
|
8637 | [valueFormatting]="dataLabelFormatting"
|
8638 | [orientation]="barOrientation.Vertical"
|
8639 | (dimensionsChanged)="dataLabelHeightChanged.emit({ size: $event, index: i })"
|
8640 | />
|
8641 | </svg:g>
|
8642 | `,
|
8643 | changeDetection: ChangeDetectionStrategy.OnPush,
|
8644 | animations: [
|
8645 | trigger('animationState', [
|
8646 | transition(':leave', [
|
8647 | style({
|
8648 | opacity: 1
|
8649 | }),
|
8650 | animate(500, style({ opacity: 0 }))
|
8651 | ])
|
8652 | ])
|
8653 | ]
|
8654 | },] }
|
8655 | ];
|
8656 | SeriesVerticalComponent.propDecorators = {
|
8657 | dims: [{ type: Input }],
|
8658 | type: [{ type: Input }],
|
8659 | series: [{ type: Input }],
|
8660 | xScale: [{ type: Input }],
|
8661 | yScale: [{ type: Input }],
|
8662 | colors: [{ type: Input }],
|
8663 | gradient: [{ type: Input }],
|
8664 | activeEntries: [{ type: Input }],
|
8665 | seriesName: [{ type: Input }],
|
8666 | tooltipDisabled: [{ type: Input }],
|
8667 | tooltipTemplate: [{ type: Input }],
|
8668 | roundEdges: [{ type: Input }],
|
8669 | animations: [{ type: Input }],
|
8670 | showDataLabel: [{ type: Input }],
|
8671 | dataLabelFormatting: [{ type: Input }],
|
8672 | noBarWhenZero: [{ type: Input }],
|
8673 | select: [{ type: Output }],
|
8674 | activate: [{ type: Output }],
|
8675 | deactivate: [{ type: Output }],
|
8676 | dataLabelHeightChanged: [{ type: Output }]
|
8677 | };
|
8678 |
|
8679 | class BarLabelComponent {
|
8680 | constructor(element) {
|
8681 | this.dimensionsChanged = new EventEmitter();
|
8682 | this.horizontalPadding = 2;
|
8683 | this.verticalPadding = 5;
|
8684 | this.element = element.nativeElement;
|
8685 | }
|
8686 | ngOnChanges(changes) {
|
8687 | this.update();
|
8688 | }
|
8689 | getSize() {
|
8690 | const h = this.element.getBoundingClientRect().height;
|
8691 | const w = this.element.getBoundingClientRect().width;
|
8692 | return { height: h, width: w, negative: this.value < 0 };
|
8693 | }
|
8694 | ngAfterViewInit() {
|
8695 | this.dimensionsChanged.emit(this.getSize());
|
8696 | }
|
8697 | update() {
|
8698 | if (this.valueFormatting) {
|
8699 | this.formatedValue = this.valueFormatting(this.value);
|
8700 | }
|
8701 | else {
|
8702 | this.formatedValue = formatLabel(this.value);
|
8703 | }
|
8704 | if (this.orientation === 'horizontal') {
|
8705 | this.x = this.barX + this.barWidth;
|
8706 |
|
8707 |
|
8708 | if (this.value < 0) {
|
8709 | this.x = this.x - this.horizontalPadding;
|
8710 | this.textAnchor = 'end';
|
8711 | }
|
8712 | else {
|
8713 | this.x = this.x + this.horizontalPadding;
|
8714 | this.textAnchor = 'start';
|
8715 | }
|
8716 | this.y = this.barY + this.barHeight / 2;
|
8717 | }
|
8718 | else {
|
8719 |
|
8720 | this.x = this.barX + this.barWidth / 2;
|
8721 | this.y = this.barY + this.barHeight;
|
8722 | if (this.value < 0) {
|
8723 | this.y = this.y + this.verticalPadding;
|
8724 | this.textAnchor = 'end';
|
8725 | }
|
8726 | else {
|
8727 | this.y = this.y - this.verticalPadding;
|
8728 | this.textAnchor = 'start';
|
8729 | }
|
8730 | this.transform = `rotate(-45, ${this.x} , ${this.y})`;
|
8731 | }
|
8732 | }
|
8733 | }
|
8734 | BarLabelComponent.decorators = [
|
8735 | { type: Component, args: [{
|
8736 | selector: 'g[ngx-charts-bar-label]',
|
8737 | template: `
|
8738 | <svg:text
|
8739 | class="textDataLabel"
|
8740 | alignment-baseline="middle"
|
8741 | [attr.text-anchor]="textAnchor"
|
8742 | [attr.transform]="transform"
|
8743 | [attr.x]="x"
|
8744 | [attr.y]="y"
|
8745 | >
|
8746 | {{ formatedValue }}
|
8747 | </svg:text>
|
8748 | `,
|
8749 | changeDetection: ChangeDetectionStrategy.OnPush,
|
8750 | styles: [".textDataLabel{font-size:11px}\n"]
|
8751 | },] }
|
8752 | ];
|
8753 | BarLabelComponent.ctorParameters = () => [
|
8754 | { type: ElementRef }
|
8755 | ];
|
8756 | BarLabelComponent.propDecorators = {
|
8757 | value: [{ type: Input }],
|
8758 | valueFormatting: [{ type: Input }],
|
8759 | barX: [{ type: Input }],
|
8760 | barY: [{ type: Input }],
|
8761 | barWidth: [{ type: Input }],
|
8762 | barHeight: [{ type: Input }],
|
8763 | orientation: [{ type: Input }],
|
8764 | dimensionsChanged: [{ type: Output }]
|
8765 | };
|
8766 |
|
8767 | class BarChartModule {
|
8768 | }
|
8769 | BarChartModule.decorators = [
|
8770 | { type: NgModule, args: [{
|
8771 | imports: [ChartCommonModule],
|
8772 | declarations: [
|
8773 | BarComponent,
|
8774 | BarHorizontalComponent,
|
8775 | BarHorizontal2DComponent,
|
8776 | BarHorizontalNormalizedComponent,
|
8777 | BarHorizontalStackedComponent,
|
8778 | BarVerticalComponent,
|
8779 | BarVertical2DComponent,
|
8780 | BarVerticalNormalizedComponent,
|
8781 | BarVerticalStackedComponent,
|
8782 | BarLabelComponent,
|
8783 | SeriesHorizontal,
|
8784 | SeriesVerticalComponent
|
8785 | ],
|
8786 | exports: [
|
8787 | BarComponent,
|
8788 | BarHorizontalComponent,
|
8789 | BarHorizontal2DComponent,
|
8790 | BarHorizontalNormalizedComponent,
|
8791 | BarHorizontalStackedComponent,
|
8792 | BarVerticalComponent,
|
8793 | BarVertical2DComponent,
|
8794 | BarVerticalNormalizedComponent,
|
8795 | BarVerticalStackedComponent,
|
8796 | BarLabelComponent,
|
8797 | SeriesHorizontal,
|
8798 | SeriesVerticalComponent
|
8799 | ]
|
8800 | },] }
|
8801 | ];
|
8802 |
|
8803 | class BoxChartComponent extends BaseChartComponent {
|
8804 | constructor() {
|
8805 | super(...arguments);
|
8806 |
|
8807 | this.legend = false;
|
8808 | this.legendPosition = LegendPosition.Right;
|
8809 | this.legendTitle = 'Legend';
|
8810 | this.showGridLines = true;
|
8811 | this.xAxis = true;
|
8812 | this.yAxis = true;
|
8813 | this.showXAxisLabel = true;
|
8814 | this.showYAxisLabel = true;
|
8815 | this.roundDomains = false;
|
8816 | this.roundEdges = true;
|
8817 | this.strokeColor = '#FFFFFF';
|
8818 | this.strokeWidth = 2;
|
8819 | this.tooltipDisabled = false;
|
8820 | this.select = new EventEmitter();
|
8821 | this.activate = new EventEmitter();
|
8822 | this.deactivate = new EventEmitter();
|
8823 |
|
8824 | this.margin = [10, 20, 10, 20];
|
8825 |
|
8826 | this.xAxisHeight = 0;
|
8827 |
|
8828 | this.yAxisWidth = 0;
|
8829 | }
|
8830 | trackBy(index, item) {
|
8831 | return item.name;
|
8832 | }
|
8833 | update() {
|
8834 | super.update();
|
8835 | this.dims = calculateViewDimensions({
|
8836 | width: this.width,
|
8837 | height: this.height,
|
8838 | margins: this.margin,
|
8839 | showXAxis: this.xAxis,
|
8840 | showYAxis: this.yAxis,
|
8841 | xAxisHeight: this.xAxisHeight,
|
8842 | yAxisWidth: this.yAxisWidth,
|
8843 | showXLabel: this.showXAxisLabel,
|
8844 | showYLabel: this.showYAxisLabel,
|
8845 | showLegend: this.legend,
|
8846 | legendPosition: this.legendPosition
|
8847 | });
|
8848 | this.xDomain = this.getXDomain();
|
8849 | this.yDomain = this.getYDomain();
|
8850 | this.seriesDomain = this.getSeriesDomain();
|
8851 | this.setScales();
|
8852 | this.setColors();
|
8853 | this.legendOptions = this.getLegendOptions();
|
8854 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
8855 | }
|
8856 | setColors() {
|
8857 | let domain = [];
|
8858 | if (this.schemeType === ScaleType.Ordinal) {
|
8859 | domain = this.seriesDomain;
|
8860 | }
|
8861 | else {
|
8862 | domain = this.yDomain;
|
8863 | }
|
8864 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
8865 | }
|
8866 | setScales() {
|
8867 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
8868 | this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
8869 | }
|
8870 | getXScale(domain, width) {
|
8871 | const scale = scaleBand()
|
8872 | .domain(domain.map(d => d.toString()))
|
8873 | .rangeRound([0, width])
|
8874 | .padding(0.5);
|
8875 | return scale;
|
8876 | }
|
8877 | getYScale(domain, height) {
|
8878 | const scale = scaleLinear().domain(domain).range([height, 0]);
|
8879 | return this.roundDomains ? scale.nice() : scale;
|
8880 | }
|
8881 | getUniqueBoxChartXDomainValues(results) {
|
8882 | const valueSet = new Set();
|
8883 | for (const result of results) {
|
8884 | valueSet.add(result.name);
|
8885 | }
|
8886 | return Array.from(valueSet);
|
8887 | }
|
8888 | getXDomain() {
|
8889 | let domain = [];
|
8890 | const values = this.getUniqueBoxChartXDomainValues(this.results);
|
8891 | let min;
|
8892 | let max;
|
8893 | if (typeof values[0] === 'string') {
|
8894 | domain = values.map(val => val.toString());
|
8895 | }
|
8896 | else if (typeof values[0] === 'number') {
|
8897 | const mappedValues = values.map(v => Number(v));
|
8898 | min = Math.min(...mappedValues);
|
8899 | max = Math.max(...mappedValues);
|
8900 | domain = [min, max];
|
8901 | }
|
8902 | else {
|
8903 | const mappedValues = values.map(v => Number(new Date(v)));
|
8904 | min = Math.min(...mappedValues);
|
8905 | max = Math.max(...mappedValues);
|
8906 | domain = [new Date(min), new Date(max)];
|
8907 | }
|
8908 | return domain;
|
8909 | }
|
8910 | getYDomain() {
|
8911 | const domain = [];
|
8912 | for (const results of this.results) {
|
8913 | for (const d of results.series) {
|
8914 | if (domain.indexOf(d.value) < 0) {
|
8915 | domain.push(d.value);
|
8916 | }
|
8917 | }
|
8918 | }
|
8919 | const values = [...domain];
|
8920 | const mappedValues = values.map(v => Number(v));
|
8921 | const min = Math.min(...mappedValues);
|
8922 | const max = Math.max(...mappedValues);
|
8923 | return [min, max];
|
8924 | }
|
8925 | getSeriesDomain() {
|
8926 | return this.results.map(d => `${d.name}`);
|
8927 | }
|
8928 | updateYAxisWidth({ width }) {
|
8929 | this.yAxisWidth = width;
|
8930 | this.update();
|
8931 | }
|
8932 | updateXAxisHeight({ height }) {
|
8933 | this.xAxisHeight = height;
|
8934 | this.update();
|
8935 | }
|
8936 | onClick(data) {
|
8937 | this.select.emit(data);
|
8938 | }
|
8939 | onActivate(data) {
|
8940 | this.activate.emit(data);
|
8941 | }
|
8942 | onDeactivate(data) {
|
8943 | this.deactivate.emit(data);
|
8944 | }
|
8945 | getLegendOptions() {
|
8946 | const legendOpts = {
|
8947 | scaleType: this.schemeType,
|
8948 | colors: this.colors,
|
8949 | domain: [],
|
8950 | position: this.legendPosition,
|
8951 | title: this.legendTitle
|
8952 | };
|
8953 | if (this.schemeType === ScaleType.Ordinal) {
|
8954 | legendOpts.domain = this.xDomain;
|
8955 | legendOpts.colors = this.colors;
|
8956 | }
|
8957 | else {
|
8958 | legendOpts.domain = this.yDomain;
|
8959 | legendOpts.colors = this.colors.scale;
|
8960 | }
|
8961 | return legendOpts;
|
8962 | }
|
8963 | }
|
8964 | BoxChartComponent.decorators = [
|
8965 | { type: Component, args: [{
|
8966 | selector: 'ngx-charts-box-chart',
|
8967 | template: `
|
8968 | <ngx-charts-chart
|
8969 | [view]="[width, height]"
|
8970 | [showLegend]="legend"
|
8971 | [legendOptions]="legendOptions"
|
8972 | [animations]="animations"
|
8973 | (legendLabelClick)="onClick($event)"
|
8974 | (legendLabelActivate)="onActivate($event)"
|
8975 | (legendLabelDeactivate)="onDeactivate($event)"
|
8976 | >
|
8977 | <svg:g [attr.transform]="transform" class="box-chart chart">
|
8978 | <svg:g
|
8979 | ngx-charts-x-axis
|
8980 | [showGridLines]="showGridLines"
|
8981 | [dims]="dims"
|
8982 | [xScale]="xScale"
|
8983 | [showLabel]="showXAxisLabel"
|
8984 | [labelText]="xAxisLabel"
|
8985 | (dimensionsChanged)="updateXAxisHeight($event)"
|
8986 | />
|
8987 | <svg:g
|
8988 | ngx-charts-y-axis
|
8989 | [showGridLines]="showGridLines"
|
8990 | [dims]="dims"
|
8991 | [yScale]="yScale"
|
8992 | [showLabel]="showYAxisLabel"
|
8993 | [labelText]="yAxisLabel"
|
8994 | (dimensionsChanged)="updateYAxisWidth($event)"
|
8995 | />
|
8996 | </svg:g>
|
8997 | <svg:g [attr.transform]="transform">
|
8998 | <svg:g *ngFor="let result of results; trackBy: trackBy">
|
8999 | <svg:g
|
9000 | ngx-charts-box-series
|
9001 | [xScale]="xScale"
|
9002 | [yScale]="yScale"
|
9003 | [colors]="colors"
|
9004 | [roundEdges]="roundEdges"
|
9005 | [strokeColor]="strokeColor"
|
9006 | [strokeWidth]="strokeWidth"
|
9007 | [tooltipDisabled]="tooltipDisabled"
|
9008 | [tooltipTemplate]="tooltipTemplate"
|
9009 | [series]="result"
|
9010 | [dims]="dims"
|
9011 | [animations]="animations"
|
9012 | [gradient]="gradient"
|
9013 | (activate)="onActivate($event)"
|
9014 | (deactivate)="onDeactivate($event)"
|
9015 | (select)="onClick($event)"
|
9016 | />
|
9017 | </svg:g>
|
9018 | </svg:g>
|
9019 | </ngx-charts-chart>
|
9020 | `,
|
9021 | changeDetection: ChangeDetectionStrategy.OnPush,
|
9022 | encapsulation: ViewEncapsulation.None,
|
9023 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
9024 | },] }
|
9025 | ];
|
9026 | BoxChartComponent.propDecorators = {
|
9027 | legend: [{ type: Input }],
|
9028 | legendPosition: [{ type: Input }],
|
9029 | legendTitle: [{ type: Input }],
|
9030 | legendOptionsConfig: [{ type: Input }],
|
9031 | showGridLines: [{ type: Input }],
|
9032 | xAxis: [{ type: Input }],
|
9033 | yAxis: [{ type: Input }],
|
9034 | showXAxisLabel: [{ type: Input }],
|
9035 | showYAxisLabel: [{ type: Input }],
|
9036 | roundDomains: [{ type: Input }],
|
9037 | xAxisLabel: [{ type: Input }],
|
9038 | yAxisLabel: [{ type: Input }],
|
9039 | roundEdges: [{ type: Input }],
|
9040 | strokeColor: [{ type: Input }],
|
9041 | strokeWidth: [{ type: Input }],
|
9042 | tooltipDisabled: [{ type: Input }],
|
9043 | gradient: [{ type: Input }],
|
9044 | select: [{ type: Output }],
|
9045 | activate: [{ type: Output }],
|
9046 | deactivate: [{ type: Output }],
|
9047 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate', { static: false },] }]
|
9048 | };
|
9049 |
|
9050 | class BoxSeriesComponent {
|
9051 | constructor() {
|
9052 | this.animations = true;
|
9053 | this.tooltipDisabled = false;
|
9054 | this.gradient = false;
|
9055 | this.select = new EventEmitter();
|
9056 | this.activate = new EventEmitter();
|
9057 | this.deactivate = new EventEmitter();
|
9058 | }
|
9059 | ngOnChanges(changes) {
|
9060 | this.update();
|
9061 | }
|
9062 | onClick(data) {
|
9063 | this.select.emit(data);
|
9064 | }
|
9065 | update() {
|
9066 | this.updateTooltipSettings();
|
9067 | const width = this.series && this.series.series.length ? Math.round(this.xScale.bandwidth()) : null;
|
9068 | const seriesName = this.series.name;
|
9069 |
|
9070 | this.counts = this.series.series;
|
9071 | const mappedCounts = this.counts.map(serie => Number(serie.value));
|
9072 | this.whiskers = [min(mappedCounts), max(mappedCounts)];
|
9073 |
|
9074 | const groupCounts = this.counts.map(item => item.value).sort((a, b) => Number(a) - Number(b));
|
9075 | this.quartiles = this.getBoxQuantiles(groupCounts);
|
9076 | this.lineCoordinates = this.getLinesCoordinates(seriesName.toString(), this.whiskers, this.quartiles, width);
|
9077 | const value = this.quartiles[1];
|
9078 | const formattedLabel = formatLabel(seriesName);
|
9079 | const box = {
|
9080 | value,
|
9081 | data: this.counts,
|
9082 | label: seriesName,
|
9083 | formattedLabel,
|
9084 | width,
|
9085 | height: 0,
|
9086 | x: 0,
|
9087 | y: 0,
|
9088 | roundEdges: this.roundEdges,
|
9089 | quartiles: this.quartiles,
|
9090 | lineCoordinates: this.lineCoordinates
|
9091 | };
|
9092 | box.height = Math.abs(this.yScale(this.quartiles[0]) - this.yScale(this.quartiles[2]));
|
9093 | box.x = this.xScale(seriesName.toString());
|
9094 | box.y = this.yScale(this.quartiles[2]);
|
9095 | box.ariaLabel = formattedLabel + ' - Median: ' + value.toLocaleString();
|
9096 | if (this.colors.scaleType === ScaleType.Ordinal) {
|
9097 | box.color = this.colors.getColor(seriesName);
|
9098 | }
|
9099 | else {
|
9100 | box.color = this.colors.getColor(this.quartiles[1]);
|
9101 | box.gradientStops = this.colors.getLinearGradientStops(this.quartiles[0], this.quartiles[2]);
|
9102 | }
|
9103 | const tooltipLabel = formattedLabel;
|
9104 | const formattedTooltipLabel = `
|
9105 | <span class="tooltip-label">${escapeLabel(tooltipLabel)}</span>
|
9106 | <span class="tooltip-val">
|
9107 | • Q1: ${this.quartiles[0]} • Q2: ${this.quartiles[1]} • Q3: ${this.quartiles[2]}<br>
|
9108 | • Min: ${this.whiskers[0]} • Max: ${this.whiskers[1]}
|
9109 | </span>`;
|
9110 | box.tooltipText = this.tooltipDisabled ? undefined : formattedTooltipLabel;
|
9111 | this.tooltipTitle = this.tooltipDisabled ? undefined : box.tooltipText;
|
9112 | this.box = box;
|
9113 | }
|
9114 | getBoxQuantiles(inputData) {
|
9115 | return [quantile(inputData, 0.25), quantile(inputData, 0.5), quantile(inputData, 0.75)];
|
9116 | }
|
9117 | getLinesCoordinates(seriesName, whiskers, quartiles, barWidth) {
|
9118 |
|
9119 | const commonX = this.xScale(seriesName);
|
9120 | const offsetX = commonX + barWidth / 2;
|
9121 | const medianLineWidth = Math.max(barWidth + 4 * this.strokeWidth, 1);
|
9122 | const whiskerLineWidth = Math.max(barWidth / 3, 1);
|
9123 | const whiskerZero = this.yScale(whiskers[0]);
|
9124 | const whiskerOne = this.yScale(whiskers[1]);
|
9125 | const median = this.yScale(quartiles[1]);
|
9126 | const topLine = {
|
9127 | v1: { x: offsetX + whiskerLineWidth / 2, y: whiskerZero },
|
9128 | v2: { x: offsetX - whiskerLineWidth / 2, y: whiskerZero }
|
9129 | };
|
9130 | const medianLine = {
|
9131 | v1: { x: offsetX + medianLineWidth / 2, y: median },
|
9132 | v2: { x: offsetX - medianLineWidth / 2, y: median }
|
9133 | };
|
9134 | const bottomLine = {
|
9135 | v1: { x: offsetX + whiskerLineWidth / 2, y: whiskerOne },
|
9136 | v2: { x: offsetX - whiskerLineWidth / 2, y: whiskerOne }
|
9137 | };
|
9138 | const verticalLine = {
|
9139 | v1: { x: offsetX, y: whiskerZero },
|
9140 | v2: { x: offsetX, y: whiskerOne }
|
9141 | };
|
9142 | return [verticalLine, topLine, medianLine, bottomLine];
|
9143 | }
|
9144 | updateTooltipSettings() {
|
9145 | if (this.tooltipDisabled) {
|
9146 | this.tooltipPlacement = undefined;
|
9147 | this.tooltipType = undefined;
|
9148 | }
|
9149 | else {
|
9150 | if (!this.tooltipPlacement) {
|
9151 | this.tooltipPlacement = PlacementTypes.Top;
|
9152 | }
|
9153 | if (!this.tooltipType) {
|
9154 | this.tooltipType = StyleTypes.tooltip;
|
9155 | }
|
9156 | }
|
9157 | }
|
9158 | }
|
9159 | BoxSeriesComponent.decorators = [
|
9160 | { type: Component, args: [{
|
9161 | selector: 'g[ngx-charts-box-series]',
|
9162 | template: `
|
9163 | <svg:g
|
9164 | ngx-charts-box
|
9165 | [@animationState]="'active'"
|
9166 | [@.disabled]="!animations"
|
9167 | [width]="box.width"
|
9168 | [height]="box.height"
|
9169 | [x]="box.x"
|
9170 | [y]="box.y"
|
9171 | [roundEdges]="box.roundEdges"
|
9172 | [fill]="box.color"
|
9173 | [gradientStops]="box.gradientStops"
|
9174 | [strokeColor]="strokeColor"
|
9175 | [strokeWidth]="strokeWidth"
|
9176 | [data]="box.data"
|
9177 | [lineCoordinates]="box.lineCoordinates"
|
9178 | [gradient]="gradient"
|
9179 | [ariaLabel]="box.ariaLabel"
|
9180 | (select)="onClick($event)"
|
9181 | (activate)="activate.emit($event)"
|
9182 | (deactivate)="deactivate.emit($event)"
|
9183 | ngx-tooltip
|
9184 | [tooltipDisabled]="tooltipDisabled"
|
9185 | [tooltipPlacement]="tooltipPlacement"
|
9186 | [tooltipType]="tooltipType"
|
9187 | [tooltipTitle]="tooltipTitle"
|
9188 | [tooltipTemplate]="tooltipTemplate"
|
9189 | [tooltipContext]="box.data"
|
9190 | [animations]="animations"
|
9191 | ></svg:g>
|
9192 | `,
|
9193 | changeDetection: ChangeDetectionStrategy.OnPush,
|
9194 | animations: [
|
9195 | trigger('animationState', [
|
9196 | transition(':leave', [
|
9197 | style({
|
9198 | opacity: 1
|
9199 | }),
|
9200 | animate(500, style({ opacity: 0 }))
|
9201 | ])
|
9202 | ])
|
9203 | ]
|
9204 | },] }
|
9205 | ];
|
9206 | BoxSeriesComponent.propDecorators = {
|
9207 | dims: [{ type: Input }],
|
9208 | series: [{ type: Input }],
|
9209 | xScale: [{ type: Input }],
|
9210 | yScale: [{ type: Input }],
|
9211 | colors: [{ type: Input }],
|
9212 | animations: [{ type: Input }],
|
9213 | strokeColor: [{ type: Input }],
|
9214 | strokeWidth: [{ type: Input }],
|
9215 | tooltipDisabled: [{ type: Input }],
|
9216 | tooltipTemplate: [{ type: Input }],
|
9217 | tooltipPlacement: [{ type: Input }],
|
9218 | tooltipType: [{ type: Input }],
|
9219 | roundEdges: [{ type: Input }],
|
9220 | gradient: [{ type: Input }],
|
9221 | select: [{ type: Output }],
|
9222 | activate: [{ type: Output }],
|
9223 | deactivate: [{ type: Output }]
|
9224 | };
|
9225 |
|
9226 | class BoxComponent {
|
9227 | constructor(element, cd) {
|
9228 | this.cd = cd;
|
9229 | this.roundEdges = true;
|
9230 | this.gradient = false;
|
9231 | this.offset = 0;
|
9232 | this.isActive = false;
|
9233 | this.animations = true;
|
9234 | this.noBarWhenZero = true;
|
9235 | this.select = new EventEmitter();
|
9236 | this.activate = new EventEmitter();
|
9237 | this.deactivate = new EventEmitter();
|
9238 | this.BarOrientation = BarOrientation;
|
9239 | this.initialized = false;
|
9240 | this.hasGradient = false;
|
9241 | this.hideBar = false;
|
9242 | this.nativeElm = element.nativeElement;
|
9243 | }
|
9244 | ngOnChanges(changes) {
|
9245 | if (!this.initialized) {
|
9246 | this.loadAnimation();
|
9247 | this.initialized = true;
|
9248 | }
|
9249 | else {
|
9250 | this.update();
|
9251 | }
|
9252 | }
|
9253 | update() {
|
9254 | this.boxStrokeWidth = Math.max(this.strokeWidth, 1);
|
9255 | this.whiskerStrokeWidth = Math.max(this.strokeWidth / 2, 1);
|
9256 | this.medianLineWidth = 1.5 * this.strokeWidth;
|
9257 | this.gradientId = 'grad' + id().toString();
|
9258 | this.gradientFill = `url(#${this.gradientId})`;
|
9259 | if (this.gradient) {
|
9260 | this.gradientStops = this.getGradient();
|
9261 | this.hasGradient = true;
|
9262 | }
|
9263 | else {
|
9264 | this.hasGradient = false;
|
9265 | }
|
9266 | this.updateLineEl();
|
9267 | this.updatePathEl();
|
9268 | this.checkToHideBar();
|
9269 | this.maskLineId = 'mask' + id().toString();
|
9270 | this.maskLine = `url(#${this.maskLineId})`;
|
9271 | if (this.cd) {
|
9272 | this.cd.markForCheck();
|
9273 | }
|
9274 | }
|
9275 | loadAnimation() {
|
9276 | this.boxPath = this.oldPath = this.getStartingPath();
|
9277 | this.oldLineCoordinates = this.getStartingLineCoordinates();
|
9278 | setTimeout(this.update.bind(this), 100);
|
9279 | }
|
9280 | updatePathEl() {
|
9281 | const nodeBar = select(this.nativeElm).selectAll('.bar');
|
9282 | const path = this.getPath();
|
9283 | if (this.animations) {
|
9284 | nodeBar
|
9285 | .attr('d', this.oldPath)
|
9286 | .transition()
|
9287 | .ease(easeSinInOut)
|
9288 | .duration(500)
|
9289 | .attrTween('d', this.pathTween(path, 4));
|
9290 | }
|
9291 | else {
|
9292 | nodeBar.attr('d', path);
|
9293 | }
|
9294 | this.oldPath = path;
|
9295 | }
|
9296 | updateLineEl() {
|
9297 | const lineEl = select(this.nativeElm).selectAll('.bar-line');
|
9298 | const lineCoordinates = this.lineCoordinates;
|
9299 | const oldLineCoordinates = this.oldLineCoordinates;
|
9300 | if (this.animations) {
|
9301 | lineEl
|
9302 | .attr('x1', (_, index) => oldLineCoordinates[index].v1.x)
|
9303 | .attr('y1', (_, index) => oldLineCoordinates[index].v1.y)
|
9304 | .attr('x2', (_, index) => oldLineCoordinates[index].v2.x)
|
9305 | .attr('y2', (_, index) => oldLineCoordinates[index].v2.y)
|
9306 | .transition()
|
9307 | .ease(easeSinInOut)
|
9308 | .duration(500)
|
9309 | .attr('x1', (_, index) => lineCoordinates[index].v1.x)
|
9310 | .attr('y1', (_, index) => lineCoordinates[index].v1.y)
|
9311 | .attr('x2', (_, index) => lineCoordinates[index].v2.x)
|
9312 | .attr('y2', (_, index) => lineCoordinates[index].v2.y);
|
9313 | }
|
9314 | else {
|
9315 | lineEl
|
9316 | .attr('x1', (_, index) => lineCoordinates[index].v1.x)
|
9317 | .attr('y1', (_, index) => lineCoordinates[index].v1.y)
|
9318 | .attr('x2', (_, index) => lineCoordinates[index].v2.x)
|
9319 | .attr('y2', (_, index) => lineCoordinates[index].v2.y);
|
9320 | }
|
9321 | this.oldLineCoordinates = [...lineCoordinates];
|
9322 | }
|
9323 | |
9324 |
|
9325 |
|
9326 |
|
9327 |
|
9328 |
|
9329 | lineTween(attr, d, index, node) {
|
9330 | const nodeLineEl = node[index];
|
9331 | return nodeLineEl[attr].baseVal.value;
|
9332 | }
|
9333 |
|
9334 | pathTween(d1, precision) {
|
9335 | return function () {
|
9336 |
|
9337 | const path0 = this;
|
9338 | const path1 = this.cloneNode();
|
9339 | path1.setAttribute('d', d1);
|
9340 | const n0 = path0 === null || path0 === void 0 ? void 0 : path0.getTotalLength();
|
9341 | const n1 = path1 === null || path1 === void 0 ? void 0 : path1.getTotalLength();
|
9342 |
|
9343 | const distances = [0];
|
9344 | let i = 0;
|
9345 | const dt = precision / Math.max(n0, n1);
|
9346 | while (i < 1) {
|
9347 | distances.push(i);
|
9348 | i += dt;
|
9349 | }
|
9350 | distances.push(1);
|
9351 |
|
9352 | const points = distances.map((t) => {
|
9353 | const p0 = path0.getPointAtLength(t * n0);
|
9354 | const p1 = path1.getPointAtLength(t * n1);
|
9355 | return interpolate([p0.x, p0.y], [p1.x, p1.y]);
|
9356 | });
|
9357 |
|
9358 | return (t) => {
|
9359 | return t < 1 ? 'M' + points.map((p) => p(t)).join('L') : d1;
|
9360 | };
|
9361 | };
|
9362 | }
|
9363 | getStartingPath() {
|
9364 | if (!this.animations) {
|
9365 | return this.getPath();
|
9366 | }
|
9367 | const radius = this.roundEdges ? 1 : 0;
|
9368 | const { x, y } = this.lineCoordinates[2].v1;
|
9369 | return roundedRect(x - this.width, y - 1, this.width, 2, radius, this.edges);
|
9370 | }
|
9371 | getPath() {
|
9372 | const radius = this.getRadius();
|
9373 | let path = '';
|
9374 | path = roundedRect(this.x, this.y, this.width, this.height, Math.min(this.height, radius), this.edges);
|
9375 | return path;
|
9376 | }
|
9377 | getStartingLineCoordinates() {
|
9378 | if (!this.animations) {
|
9379 | return [...this.lineCoordinates];
|
9380 | }
|
9381 | const lineCoordinates = cloneDeep(this.lineCoordinates);
|
9382 | lineCoordinates[1].v1.y = lineCoordinates[1].v2.y = lineCoordinates[3].v1.y = lineCoordinates[3].v2.y = lineCoordinates[0].v1.y = lineCoordinates[0].v2.y =
|
9383 | lineCoordinates[2].v1.y;
|
9384 | return lineCoordinates;
|
9385 | }
|
9386 | getRadius() {
|
9387 | let radius = 0;
|
9388 | if (this.roundEdges && this.height > 5 && this.width > 5) {
|
9389 | radius = Math.floor(Math.min(5, this.height / 2, this.width / 2));
|
9390 | }
|
9391 | return radius;
|
9392 | }
|
9393 | getGradient() {
|
9394 | return [
|
9395 | {
|
9396 | offset: 0,
|
9397 | color: this.fill,
|
9398 | opacity: this.getStartOpacity()
|
9399 | },
|
9400 | {
|
9401 | offset: 100,
|
9402 | color: this.fill,
|
9403 | opacity: 1
|
9404 | }
|
9405 | ];
|
9406 | }
|
9407 | getStartOpacity() {
|
9408 | if (this.roundEdges) {
|
9409 | return 0.2;
|
9410 | }
|
9411 | else {
|
9412 | return 0.5;
|
9413 | }
|
9414 | }
|
9415 | get edges() {
|
9416 | let edges = [false, false, false, false];
|
9417 | if (this.roundEdges) {
|
9418 | edges = [true, true, true, true];
|
9419 | }
|
9420 | return edges;
|
9421 | }
|
9422 | onMouseEnter() {
|
9423 | this.activate.emit(this.data);
|
9424 | }
|
9425 | onMouseLeave() {
|
9426 | this.deactivate.emit(this.data);
|
9427 | }
|
9428 | checkToHideBar() {
|
9429 | this.hideBar = this.noBarWhenZero && this.height === 0;
|
9430 | }
|
9431 | }
|
9432 | BoxComponent.decorators = [
|
9433 | { type: Component, args: [{
|
9434 | selector: 'g[ngx-charts-box]',
|
9435 | template: `
|
9436 | <svg:defs>
|
9437 | <svg:g
|
9438 | *ngIf="hasGradient"
|
9439 | ngx-charts-svg-linear-gradient
|
9440 | [orientation]="BarOrientation.Vertical"
|
9441 | [name]="gradientId"
|
9442 | [stops]="gradientStops"
|
9443 | />
|
9444 | <svg:mask [attr.id]="maskLineId">
|
9445 | <svg:g>
|
9446 | <rect height="100%" width="100%" fill="white" fill-opacity="1" />
|
9447 | <path class="bar" [attr.d]="boxPath" fill="black" fill-opacity="1" />
|
9448 | </svg:g>
|
9449 | </svg:mask>
|
9450 | </svg:defs>
|
9451 | <svg:g>
|
9452 | <svg:path
|
9453 | class="bar"
|
9454 | role="img"
|
9455 | tabIndex="-1"
|
9456 | [class.active]="isActive"
|
9457 | [class.hidden]="hideBar"
|
9458 | [attr.d]="boxPath"
|
9459 | [attr.stroke]="strokeColor"
|
9460 | [attr.stroke-width]="boxStrokeWidth"
|
9461 | [attr.aria-label]="ariaLabel"
|
9462 | [attr.fill]="hasGradient ? gradientFill : fill"
|
9463 | (click)="select.emit(data)"
|
9464 | />
|
9465 | <svg:line
|
9466 | *ngFor="let line of lineCoordinates; let i = index"
|
9467 | class="bar-line"
|
9468 | [class.hidden]="hideBar"
|
9469 | [attr.x1]="line.v1.x"
|
9470 | [attr.y1]="line.v1.y"
|
9471 | [attr.x2]="line.v2.x"
|
9472 | [attr.y2]="line.v2.y"
|
9473 | [attr.stroke]="strokeColor"
|
9474 | [attr.stroke-width]="i === 2 ? medianLineWidth : whiskerStrokeWidth"
|
9475 | [attr.mask]="i ? undefined : maskLine"
|
9476 | fill="none"
|
9477 | />
|
9478 | </svg:g>
|
9479 | `,
|
9480 | changeDetection: ChangeDetectionStrategy.OnPush
|
9481 | },] }
|
9482 | ];
|
9483 | BoxComponent.ctorParameters = () => [
|
9484 | { type: ElementRef },
|
9485 | { type: ChangeDetectorRef }
|
9486 | ];
|
9487 | BoxComponent.propDecorators = {
|
9488 | strokeColor: [{ type: Input }],
|
9489 | strokeWidth: [{ type: Input }],
|
9490 | fill: [{ type: Input }],
|
9491 | data: [{ type: Input }],
|
9492 | width: [{ type: Input }],
|
9493 | height: [{ type: Input }],
|
9494 | x: [{ type: Input }],
|
9495 | y: [{ type: Input }],
|
9496 | lineCoordinates: [{ type: Input }],
|
9497 | roundEdges: [{ type: Input }],
|
9498 | gradient: [{ type: Input }],
|
9499 | gradientStops: [{ type: Input }],
|
9500 | offset: [{ type: Input }],
|
9501 | isActive: [{ type: Input }],
|
9502 | animations: [{ type: Input }],
|
9503 | ariaLabel: [{ type: Input }],
|
9504 | noBarWhenZero: [{ type: Input }],
|
9505 | select: [{ type: Output }],
|
9506 | activate: [{ type: Output }],
|
9507 | deactivate: [{ type: Output }],
|
9508 | onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
9509 | onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
|
9510 | };
|
9511 |
|
9512 | class BoxChartModule {
|
9513 | }
|
9514 | BoxChartModule.decorators = [
|
9515 | { type: NgModule, args: [{
|
9516 | imports: [ChartCommonModule],
|
9517 | declarations: [BoxChartComponent, BoxSeriesComponent, BoxComponent],
|
9518 | exports: [BoxChartComponent, BoxSeriesComponent, BoxComponent]
|
9519 | },] }
|
9520 | ];
|
9521 |
|
9522 | function getDomain(values, scaleType, autoScale, minVal, maxVal) {
|
9523 | let domain = [];
|
9524 | if (scaleType === ScaleType.Linear) {
|
9525 | values = values.map(v => Number(v));
|
9526 | if (!autoScale) {
|
9527 | values.push(0);
|
9528 | }
|
9529 | }
|
9530 | if (scaleType === ScaleType.Time || scaleType === ScaleType.Linear) {
|
9531 | const min = minVal ? minVal : Math.min(...values);
|
9532 | const max = maxVal ? maxVal : Math.max(...values);
|
9533 | domain = [min, max];
|
9534 | }
|
9535 | else {
|
9536 | domain = values;
|
9537 | }
|
9538 | return domain;
|
9539 | }
|
9540 | function getScale(domain, range, scaleType, roundDomains) {
|
9541 | switch (scaleType) {
|
9542 | case ScaleType.Time:
|
9543 | return scaleTime().range(range).domain(domain);
|
9544 | case ScaleType.Linear: {
|
9545 | const scale = scaleLinear().range(range).domain(domain);
|
9546 | if (roundDomains) {
|
9547 | return scale.nice();
|
9548 | }
|
9549 | return scale;
|
9550 | }
|
9551 | case ScaleType.Ordinal:
|
9552 | return scalePoint()
|
9553 | .range([range[0], range[1]])
|
9554 | .domain(domain.map(r => r.toString()));
|
9555 | default:
|
9556 | return undefined;
|
9557 | }
|
9558 | }
|
9559 |
|
9560 | class BubbleChartComponent extends BaseChartComponent {
|
9561 | constructor() {
|
9562 | super(...arguments);
|
9563 | this.showGridLines = true;
|
9564 | this.legend = false;
|
9565 | this.legendTitle = 'Legend';
|
9566 | this.legendPosition = LegendPosition.Right;
|
9567 | this.xAxis = true;
|
9568 | this.yAxis = true;
|
9569 | this.trimXAxisTicks = true;
|
9570 | this.trimYAxisTicks = true;
|
9571 | this.rotateXAxisTicks = true;
|
9572 | this.maxXAxisTickLength = 16;
|
9573 | this.maxYAxisTickLength = 16;
|
9574 | this.roundDomains = false;
|
9575 | this.maxRadius = 10;
|
9576 | this.minRadius = 3;
|
9577 | this.schemeType = ScaleType.Ordinal;
|
9578 | this.tooltipDisabled = false;
|
9579 | this.activate = new EventEmitter();
|
9580 | this.deactivate = new EventEmitter();
|
9581 | this.scaleType = ScaleType.Linear;
|
9582 | this.margin = [10, 20, 10, 20];
|
9583 | this.bubblePadding = [0, 0, 0, 0];
|
9584 | this.xAxisHeight = 0;
|
9585 | this.yAxisWidth = 0;
|
9586 | this.activeEntries = [];
|
9587 | }
|
9588 | update() {
|
9589 | super.update();
|
9590 | this.dims = calculateViewDimensions({
|
9591 | width: this.width,
|
9592 | height: this.height,
|
9593 | margins: this.margin,
|
9594 | showXAxis: this.xAxis,
|
9595 | showYAxis: this.yAxis,
|
9596 | xAxisHeight: this.xAxisHeight,
|
9597 | yAxisWidth: this.yAxisWidth,
|
9598 | showXLabel: this.showXAxisLabel,
|
9599 | showYLabel: this.showYAxisLabel,
|
9600 | showLegend: this.legend,
|
9601 | legendType: this.schemeType,
|
9602 | legendPosition: this.legendPosition
|
9603 | });
|
9604 | this.seriesDomain = this.results.map(d => d.name);
|
9605 | this.rDomain = this.getRDomain();
|
9606 | this.xDomain = this.getXDomain();
|
9607 | this.yDomain = this.getYDomain();
|
9608 | this.transform = `translate(${this.dims.xOffset},${this.margin[0]})`;
|
9609 | const colorDomain = this.schemeType === ScaleType.Ordinal ? this.seriesDomain : this.rDomain;
|
9610 | this.colors = new ColorHelper(this.scheme, this.schemeType, colorDomain, this.customColors);
|
9611 | this.data = this.results;
|
9612 | this.minRadius = Math.max(this.minRadius, 1);
|
9613 | this.maxRadius = Math.max(this.maxRadius, 1);
|
9614 | this.rScale = this.getRScale(this.rDomain, [this.minRadius, this.maxRadius]);
|
9615 | this.bubblePadding = [0, 0, 0, 0];
|
9616 | this.setScales();
|
9617 | this.bubblePadding = this.getBubblePadding();
|
9618 | this.setScales();
|
9619 | this.legendOptions = this.getLegendOptions();
|
9620 | this.clipPathId = 'clip' + id().toString();
|
9621 | this.clipPath = `url(#${this.clipPathId})`;
|
9622 | }
|
9623 | hideCircles() {
|
9624 | this.deactivateAll();
|
9625 | }
|
9626 | onClick(data, series) {
|
9627 | if (series) {
|
9628 | data.series = series.name;
|
9629 | }
|
9630 | this.select.emit(data);
|
9631 | }
|
9632 | getBubblePadding() {
|
9633 | let yMin = 0;
|
9634 | let xMin = 0;
|
9635 | let yMax = this.dims.height;
|
9636 | let xMax = this.dims.width;
|
9637 | for (const s of this.data) {
|
9638 | for (const d of s.series) {
|
9639 | const r = this.rScale(d.r);
|
9640 | const cx = this.xScaleType === ScaleType.Linear ? this.xScale(Number(d.x)) : this.xScale(d.x);
|
9641 | const cy = this.yScaleType === ScaleType.Linear ? this.yScale(Number(d.y)) : this.yScale(d.y);
|
9642 | xMin = Math.max(r - cx, xMin);
|
9643 | yMin = Math.max(r - cy, yMin);
|
9644 | yMax = Math.max(cy + r, yMax);
|
9645 | xMax = Math.max(cx + r, xMax);
|
9646 | }
|
9647 | }
|
9648 | xMax = Math.max(xMax - this.dims.width, 0);
|
9649 | yMax = Math.max(yMax - this.dims.height, 0);
|
9650 | return [yMin, xMax, yMax, xMin];
|
9651 | }
|
9652 | setScales() {
|
9653 | let width = this.dims.width;
|
9654 | if (this.xScaleMin === undefined && this.xScaleMax === undefined) {
|
9655 | width = width - this.bubblePadding[1];
|
9656 | }
|
9657 | let height = this.dims.height;
|
9658 | if (this.yScaleMin === undefined && this.yScaleMax === undefined) {
|
9659 | height = height - this.bubblePadding[2];
|
9660 | }
|
9661 | this.xScale = this.getXScale(this.xDomain, width);
|
9662 | this.yScale = this.getYScale(this.yDomain, height);
|
9663 | }
|
9664 | getYScale(domain, height) {
|
9665 | return getScale(domain, [height, this.bubblePadding[0]], this.yScaleType, this.roundDomains);
|
9666 | }
|
9667 | getXScale(domain, width) {
|
9668 | return getScale(domain, [this.bubblePadding[3], width], this.xScaleType, this.roundDomains);
|
9669 | }
|
9670 | getRScale(domain, range) {
|
9671 | const scale = scaleLinear().range(range).domain(domain);
|
9672 | return this.roundDomains ? scale.nice() : scale;
|
9673 | }
|
9674 | getLegendOptions() {
|
9675 | const opts = {
|
9676 | scaleType: this.schemeType,
|
9677 | colors: undefined,
|
9678 | domain: [],
|
9679 | position: this.legendPosition,
|
9680 | title: undefined
|
9681 | };
|
9682 | if (opts.scaleType === ScaleType.Ordinal) {
|
9683 | opts.domain = this.seriesDomain;
|
9684 | opts.colors = this.colors;
|
9685 | opts.title = this.legendTitle;
|
9686 | }
|
9687 | else {
|
9688 | opts.domain = this.rDomain;
|
9689 | opts.colors = this.colors.scale;
|
9690 | }
|
9691 | return opts;
|
9692 | }
|
9693 | getXDomain() {
|
9694 | const values = [];
|
9695 | for (const results of this.results) {
|
9696 | for (const d of results.series) {
|
9697 | if (!values.includes(d.x)) {
|
9698 | values.push(d.x);
|
9699 | }
|
9700 | }
|
9701 | }
|
9702 | this.xScaleType = getScaleType(values);
|
9703 | return getDomain(values, this.xScaleType, this.autoScale, this.xScaleMin, this.xScaleMax);
|
9704 | }
|
9705 | getYDomain() {
|
9706 | const values = [];
|
9707 | for (const results of this.results) {
|
9708 | for (const d of results.series) {
|
9709 | if (!values.includes(d.y)) {
|
9710 | values.push(d.y);
|
9711 | }
|
9712 | }
|
9713 | }
|
9714 | this.yScaleType = getScaleType(values);
|
9715 | return getDomain(values, this.yScaleType, this.autoScale, this.yScaleMin, this.yScaleMax);
|
9716 | }
|
9717 | getRDomain() {
|
9718 | let min = Infinity;
|
9719 | let max = -Infinity;
|
9720 | for (const results of this.results) {
|
9721 | for (const d of results.series) {
|
9722 | const value = Number(d.r) || 1;
|
9723 | min = Math.min(min, value);
|
9724 | max = Math.max(max, value);
|
9725 | }
|
9726 | }
|
9727 | return [min, max];
|
9728 | }
|
9729 | updateYAxisWidth({ width }) {
|
9730 | this.yAxisWidth = width;
|
9731 | this.update();
|
9732 | }
|
9733 | updateXAxisHeight({ height }) {
|
9734 | this.xAxisHeight = height;
|
9735 | this.update();
|
9736 | }
|
9737 | onActivate(item) {
|
9738 | const idx = this.activeEntries.findIndex(d => {
|
9739 | return d.name === item.name;
|
9740 | });
|
9741 | if (idx > -1) {
|
9742 | return;
|
9743 | }
|
9744 | this.activeEntries = [item, ...this.activeEntries];
|
9745 | this.activate.emit({ value: item, entries: this.activeEntries });
|
9746 | }
|
9747 | onDeactivate(item) {
|
9748 | const idx = this.activeEntries.findIndex(d => {
|
9749 | return d.name === item.name;
|
9750 | });
|
9751 | this.activeEntries.splice(idx, 1);
|
9752 | this.activeEntries = [...this.activeEntries];
|
9753 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
9754 | }
|
9755 | deactivateAll() {
|
9756 | this.activeEntries = [...this.activeEntries];
|
9757 | for (const entry of this.activeEntries) {
|
9758 | this.deactivate.emit({ value: entry, entries: [] });
|
9759 | }
|
9760 | this.activeEntries = [];
|
9761 | }
|
9762 | trackBy(index, item) {
|
9763 | return `${item.name}`;
|
9764 | }
|
9765 | }
|
9766 | BubbleChartComponent.decorators = [
|
9767 | { type: Component, args: [{
|
9768 | selector: 'ngx-charts-bubble-chart',
|
9769 | template: `
|
9770 | <ngx-charts-chart
|
9771 | [view]="[width, height]"
|
9772 | [showLegend]="legend"
|
9773 | [activeEntries]="activeEntries"
|
9774 | [legendOptions]="legendOptions"
|
9775 | [animations]="animations"
|
9776 | (legendLabelClick)="onClick($event)"
|
9777 | (legendLabelActivate)="onActivate($event)"
|
9778 | (legendLabelDeactivate)="onDeactivate($event)"
|
9779 | >
|
9780 | <svg:defs>
|
9781 | <svg:clipPath [attr.id]="clipPathId">
|
9782 | <svg:rect
|
9783 | [attr.width]="dims.width + 10"
|
9784 | [attr.height]="dims.height + 10"
|
9785 | [attr.transform]="'translate(-5, -5)'"
|
9786 | />
|
9787 | </svg:clipPath>
|
9788 | </svg:defs>
|
9789 | <svg:g [attr.transform]="transform" class="bubble-chart chart">
|
9790 | <svg:g
|
9791 | ngx-charts-x-axis
|
9792 | *ngIf="xAxis"
|
9793 | [showGridLines]="showGridLines"
|
9794 | [dims]="dims"
|
9795 | [xScale]="xScale"
|
9796 | [showLabel]="showXAxisLabel"
|
9797 | [labelText]="xAxisLabel"
|
9798 | [trimTicks]="trimXAxisTicks"
|
9799 | [rotateTicks]="rotateXAxisTicks"
|
9800 | [maxTickLength]="maxXAxisTickLength"
|
9801 | [tickFormatting]="xAxisTickFormatting"
|
9802 | [ticks]="xAxisTicks"
|
9803 | (dimensionsChanged)="updateXAxisHeight($event)"
|
9804 | />
|
9805 | <svg:g
|
9806 | ngx-charts-y-axis
|
9807 | *ngIf="yAxis"
|
9808 | [showGridLines]="showGridLines"
|
9809 | [yScale]="yScale"
|
9810 | [dims]="dims"
|
9811 | [showLabel]="showYAxisLabel"
|
9812 | [labelText]="yAxisLabel"
|
9813 | [trimTicks]="trimYAxisTicks"
|
9814 | [maxTickLength]="maxYAxisTickLength"
|
9815 | [tickFormatting]="yAxisTickFormatting"
|
9816 | [ticks]="yAxisTicks"
|
9817 | (dimensionsChanged)="updateYAxisWidth($event)"
|
9818 | />
|
9819 | <svg:rect
|
9820 | class="bubble-chart-area"
|
9821 | x="0"
|
9822 | y="0"
|
9823 | [attr.width]="dims.width"
|
9824 | [attr.height]="dims.height"
|
9825 | style="fill: rgb(255, 0, 0); opacity: 0; cursor: 'auto';"
|
9826 | (mouseenter)="deactivateAll()"
|
9827 | />
|
9828 | <svg:g [attr.clip-path]="clipPath">
|
9829 | <svg:g *ngFor="let series of data; trackBy: trackBy" [@animationState]="'active'">
|
9830 | <svg:g
|
9831 | ngx-charts-bubble-series
|
9832 | [xScale]="xScale"
|
9833 | [yScale]="yScale"
|
9834 | [rScale]="rScale"
|
9835 | [xScaleType]="xScaleType"
|
9836 | [yScaleType]="yScaleType"
|
9837 | [xAxisLabel]="xAxisLabel"
|
9838 | [yAxisLabel]="yAxisLabel"
|
9839 | [colors]="colors"
|
9840 | [data]="series"
|
9841 | [activeEntries]="activeEntries"
|
9842 | [tooltipDisabled]="tooltipDisabled"
|
9843 | [tooltipTemplate]="tooltipTemplate"
|
9844 | (select)="onClick($event, series)"
|
9845 | (activate)="onActivate($event)"
|
9846 | (deactivate)="onDeactivate($event)"
|
9847 | />
|
9848 | </svg:g>
|
9849 | </svg:g>
|
9850 | </svg:g>
|
9851 | </ngx-charts-chart>
|
9852 | `,
|
9853 | changeDetection: ChangeDetectionStrategy.OnPush,
|
9854 | encapsulation: ViewEncapsulation.None,
|
9855 | animations: [
|
9856 | trigger('animationState', [
|
9857 | transition(':leave', [
|
9858 | style({
|
9859 | opacity: 1
|
9860 | }),
|
9861 | animate(500, style({
|
9862 | opacity: 0
|
9863 | }))
|
9864 | ])
|
9865 | ])
|
9866 | ],
|
9867 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
9868 | },] }
|
9869 | ];
|
9870 | BubbleChartComponent.propDecorators = {
|
9871 | showGridLines: [{ type: Input }],
|
9872 | legend: [{ type: Input }],
|
9873 | legendTitle: [{ type: Input }],
|
9874 | legendPosition: [{ type: Input }],
|
9875 | xAxis: [{ type: Input }],
|
9876 | yAxis: [{ type: Input }],
|
9877 | showXAxisLabel: [{ type: Input }],
|
9878 | showYAxisLabel: [{ type: Input }],
|
9879 | xAxisLabel: [{ type: Input }],
|
9880 | yAxisLabel: [{ type: Input }],
|
9881 | trimXAxisTicks: [{ type: Input }],
|
9882 | trimYAxisTicks: [{ type: Input }],
|
9883 | rotateXAxisTicks: [{ type: Input }],
|
9884 | maxXAxisTickLength: [{ type: Input }],
|
9885 | maxYAxisTickLength: [{ type: Input }],
|
9886 | xAxisTickFormatting: [{ type: Input }],
|
9887 | yAxisTickFormatting: [{ type: Input }],
|
9888 | xAxisTicks: [{ type: Input }],
|
9889 | yAxisTicks: [{ type: Input }],
|
9890 | roundDomains: [{ type: Input }],
|
9891 | maxRadius: [{ type: Input }],
|
9892 | minRadius: [{ type: Input }],
|
9893 | autoScale: [{ type: Input }],
|
9894 | schemeType: [{ type: Input }],
|
9895 | tooltipDisabled: [{ type: Input }],
|
9896 | xScaleMin: [{ type: Input }],
|
9897 | xScaleMax: [{ type: Input }],
|
9898 | yScaleMin: [{ type: Input }],
|
9899 | yScaleMax: [{ type: Input }],
|
9900 | activate: [{ type: Output }],
|
9901 | deactivate: [{ type: Output }],
|
9902 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
9903 | hideCircles: [{ type: HostListener, args: ['mouseleave',] }]
|
9904 | };
|
9905 |
|
9906 | class BubbleSeriesComponent {
|
9907 | constructor() {
|
9908 | this.tooltipDisabled = false;
|
9909 | this.select = new EventEmitter();
|
9910 | this.activate = new EventEmitter();
|
9911 | this.deactivate = new EventEmitter();
|
9912 | this.placementTypes = PlacementTypes;
|
9913 | this.styleTypes = StyleTypes;
|
9914 | }
|
9915 | ngOnChanges(changes) {
|
9916 | this.update();
|
9917 | }
|
9918 | update() {
|
9919 | this.circles = this.getCircles();
|
9920 | }
|
9921 | getCircles() {
|
9922 | const seriesName = this.data.name;
|
9923 | return this.data.series
|
9924 | .map((d, i) => {
|
9925 | if (typeof d.y !== 'undefined' && typeof d.x !== 'undefined') {
|
9926 | const y = d.y;
|
9927 | const x = d.x;
|
9928 | const r = d.r;
|
9929 | const radius = this.rScale(r || 1);
|
9930 | const tooltipLabel = formatLabel(d.name);
|
9931 | const cx = this.xScaleType === ScaleType.Linear ? this.xScale(Number(x)) : this.xScale(x);
|
9932 | const cy = this.yScaleType === ScaleType.Linear ? this.yScale(Number(y)) : this.yScale(y);
|
9933 | const color = this.colors.scaleType === ScaleType.Linear ? this.colors.getColor(r) : this.colors.getColor(seriesName);
|
9934 | const isActive = !this.activeEntries.length ? true : this.isActive({ name: seriesName });
|
9935 | const opacity = isActive ? 1 : 0.3;
|
9936 | const data = Object.assign({}, d, {
|
9937 | series: seriesName,
|
9938 | name: d.name,
|
9939 | value: d.y,
|
9940 | x: d.x,
|
9941 | radius: d.r
|
9942 | });
|
9943 | return {
|
9944 | data,
|
9945 | x,
|
9946 | y,
|
9947 | r,
|
9948 | classNames: [`circle-data-${i}`],
|
9949 | value: y,
|
9950 | label: x,
|
9951 | cx,
|
9952 | cy,
|
9953 | radius,
|
9954 | tooltipLabel,
|
9955 | color,
|
9956 | opacity,
|
9957 | seriesName,
|
9958 | isActive,
|
9959 | transform: `translate(${cx},${cy})`
|
9960 | };
|
9961 | }
|
9962 | })
|
9963 | .filter(circle => circle !== undefined);
|
9964 | }
|
9965 | getTooltipText(circle) {
|
9966 | const hasRadius = typeof circle.r !== 'undefined';
|
9967 | const hasTooltipLabel = circle.tooltipLabel && circle.tooltipLabel.length;
|
9968 | const hasSeriesName = circle.seriesName && circle.seriesName.length;
|
9969 | const radiusValue = hasRadius ? formatLabel(circle.r) : '';
|
9970 | const xAxisLabel = this.xAxisLabel && this.xAxisLabel !== '' ? `${this.xAxisLabel}:` : '';
|
9971 | const yAxisLabel = this.yAxisLabel && this.yAxisLabel !== '' ? `${this.yAxisLabel}:` : '';
|
9972 | const x = formatLabel(circle.x);
|
9973 | const y = formatLabel(circle.y);
|
9974 | const name = hasSeriesName && hasTooltipLabel
|
9975 | ? `${circle.seriesName} • ${circle.tooltipLabel}`
|
9976 | : circle.seriesName + circle.tooltipLabel;
|
9977 | const tooltipTitle = hasSeriesName || hasTooltipLabel ? `<span class="tooltip-label">${escapeLabel(name)}</span>` : '';
|
9978 | return `
|
9979 | ${tooltipTitle}
|
9980 | <span class="tooltip-label">
|
9981 | <label>${escapeLabel(xAxisLabel)}</label> ${escapeLabel(x)}<br />
|
9982 | <label>${escapeLabel(yAxisLabel)}</label> ${escapeLabel(y)}
|
9983 | </span>
|
9984 | <span class="tooltip-val">
|
9985 | ${escapeLabel(radiusValue)}
|
9986 | </span>
|
9987 | `;
|
9988 | }
|
9989 | onClick(data) {
|
9990 | this.select.emit(data);
|
9991 | }
|
9992 | isActive(entry) {
|
9993 | if (!this.activeEntries)
|
9994 | return false;
|
9995 | const item = this.activeEntries.find(d => {
|
9996 | return entry.name === d.name;
|
9997 | });
|
9998 | return item !== undefined;
|
9999 | }
|
10000 | isVisible(circle) {
|
10001 | if (this.activeEntries.length > 0) {
|
10002 | return this.isActive({ name: circle.seriesName });
|
10003 | }
|
10004 | return circle.opacity !== 0;
|
10005 | }
|
10006 | activateCircle(circle) {
|
10007 | circle.barVisible = true;
|
10008 | this.activate.emit({ name: this.data.name });
|
10009 | }
|
10010 | deactivateCircle(circle) {
|
10011 | circle.barVisible = false;
|
10012 | this.deactivate.emit({ name: this.data.name });
|
10013 | }
|
10014 | trackBy(index, circle) {
|
10015 | return `${circle.data.series} ${circle.data.name}`;
|
10016 | }
|
10017 | }
|
10018 | BubbleSeriesComponent.decorators = [
|
10019 | { type: Component, args: [{
|
10020 | selector: 'g[ngx-charts-bubble-series]',
|
10021 | template: `
|
10022 | <svg:g *ngFor="let circle of circles; trackBy: trackBy">
|
10023 | <svg:g [attr.transform]="circle.transform">
|
10024 | <svg:g
|
10025 | ngx-charts-circle
|
10026 | [@animationState]="'active'"
|
10027 | class="circle"
|
10028 | [cx]="0"
|
10029 | [cy]="0"
|
10030 | [r]="circle.radius"
|
10031 | [fill]="circle.color"
|
10032 | [style.opacity]="circle.opacity"
|
10033 | [class.active]="circle.isActive"
|
10034 | [pointerEvents]="'all'"
|
10035 | [data]="circle.value"
|
10036 | [classNames]="circle.classNames"
|
10037 | (select)="onClick(circle.data)"
|
10038 | (activate)="activateCircle(circle)"
|
10039 | (deactivate)="deactivateCircle(circle)"
|
10040 | ngx-tooltip
|
10041 | [tooltipDisabled]="tooltipDisabled"
|
10042 | [tooltipPlacement]="placementTypes.Top"
|
10043 | [tooltipType]="styleTypes.tooltip"
|
10044 | [tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(circle)"
|
10045 | [tooltipTemplate]="tooltipTemplate"
|
10046 | [tooltipContext]="circle.data"
|
10047 | />
|
10048 | </svg:g>
|
10049 | </svg:g>
|
10050 | `,
|
10051 | changeDetection: ChangeDetectionStrategy.OnPush,
|
10052 | animations: [
|
10053 | trigger('animationState', [
|
10054 | transition(':enter', [
|
10055 | style({
|
10056 | opacity: 0,
|
10057 | transform: 'scale(0)'
|
10058 | }),
|
10059 | animate(250, style({ opacity: 1, transform: 'scale(1)' }))
|
10060 | ])
|
10061 | ])
|
10062 | ]
|
10063 | },] }
|
10064 | ];
|
10065 | BubbleSeriesComponent.propDecorators = {
|
10066 | data: [{ type: Input }],
|
10067 | xScale: [{ type: Input }],
|
10068 | yScale: [{ type: Input }],
|
10069 | rScale: [{ type: Input }],
|
10070 | xScaleType: [{ type: Input }],
|
10071 | yScaleType: [{ type: Input }],
|
10072 | colors: [{ type: Input }],
|
10073 | visibleValue: [{ type: Input }],
|
10074 | activeEntries: [{ type: Input }],
|
10075 | xAxisLabel: [{ type: Input }],
|
10076 | yAxisLabel: [{ type: Input }],
|
10077 | tooltipDisabled: [{ type: Input }],
|
10078 | tooltipTemplate: [{ type: Input }],
|
10079 | select: [{ type: Output }],
|
10080 | activate: [{ type: Output }],
|
10081 | deactivate: [{ type: Output }]
|
10082 | };
|
10083 |
|
10084 | class BubbleChartModule {
|
10085 | }
|
10086 | BubbleChartModule.decorators = [
|
10087 | { type: NgModule, args: [{
|
10088 | imports: [ChartCommonModule],
|
10089 | declarations: [BubbleChartComponent, BubbleSeriesComponent],
|
10090 | exports: [BubbleChartComponent, BubbleSeriesComponent]
|
10091 | },] }
|
10092 | ];
|
10093 |
|
10094 | class HeatMapCellComponent {
|
10095 | constructor(element) {
|
10096 | this.gradient = false;
|
10097 | this.animations = true;
|
10098 | this.select = new EventEmitter();
|
10099 | this.activate = new EventEmitter();
|
10100 | this.deactivate = new EventEmitter();
|
10101 | this.barOrientation = BarOrientation;
|
10102 | this.element = element.nativeElement;
|
10103 | }
|
10104 | ngOnChanges(changes) {
|
10105 | this.transform = `translate(${this.x} , ${this.y})`;
|
10106 | this.startOpacity = 0.3;
|
10107 | this.gradientId = 'grad' + id().toString();
|
10108 | this.gradientUrl = `url(#${this.gradientId})`;
|
10109 | this.gradientStops = this.getGradientStops();
|
10110 | if (this.animations) {
|
10111 | this.loadAnimation();
|
10112 | }
|
10113 | }
|
10114 | getGradientStops() {
|
10115 | return [
|
10116 | {
|
10117 | offset: 0,
|
10118 | color: this.fill,
|
10119 | opacity: this.startOpacity
|
10120 | },
|
10121 | {
|
10122 | offset: 100,
|
10123 | color: this.fill,
|
10124 | opacity: 1
|
10125 | }
|
10126 | ];
|
10127 | }
|
10128 | loadAnimation() {
|
10129 | const node = select(this.element).select('.cell');
|
10130 | node.attr('opacity', 0);
|
10131 | this.animateToCurrentForm();
|
10132 | }
|
10133 | animateToCurrentForm() {
|
10134 | const node = select(this.element).select('.cell');
|
10135 | node.transition().duration(750).attr('opacity', 1);
|
10136 | }
|
10137 | onClick() {
|
10138 | this.select.emit(this.data);
|
10139 | }
|
10140 | onMouseEnter() {
|
10141 | this.activate.emit(this.data);
|
10142 | }
|
10143 | onMouseLeave() {
|
10144 | this.deactivate.emit(this.data);
|
10145 | }
|
10146 | }
|
10147 | HeatMapCellComponent.decorators = [
|
10148 | { type: Component, args: [{
|
10149 | selector: 'g[ngx-charts-heat-map-cell]',
|
10150 | template: `
|
10151 | <svg:g [attr.transform]="transform" class="cell">
|
10152 | <defs *ngIf="gradient">
|
10153 | <svg:g
|
10154 | ngx-charts-svg-linear-gradient
|
10155 | [orientation]="barOrientation.Vertical"
|
10156 | [name]="gradientId"
|
10157 | [stops]="gradientStops"
|
10158 | />
|
10159 | </defs>
|
10160 | <svg:rect
|
10161 | [attr.fill]="gradient ? gradientUrl : fill"
|
10162 | rx="3"
|
10163 | [attr.width]="width"
|
10164 | [attr.height]="height"
|
10165 | class="cell"
|
10166 | (click)="onClick()"
|
10167 | />
|
10168 | </svg:g>
|
10169 | `,
|
10170 | changeDetection: ChangeDetectionStrategy.OnPush
|
10171 | },] }
|
10172 | ];
|
10173 | HeatMapCellComponent.ctorParameters = () => [
|
10174 | { type: ElementRef }
|
10175 | ];
|
10176 | HeatMapCellComponent.propDecorators = {
|
10177 | fill: [{ type: Input }],
|
10178 | x: [{ type: Input }],
|
10179 | y: [{ type: Input }],
|
10180 | width: [{ type: Input }],
|
10181 | height: [{ type: Input }],
|
10182 | data: [{ type: Input }],
|
10183 | gradient: [{ type: Input }],
|
10184 | animations: [{ type: Input }],
|
10185 | select: [{ type: Output }],
|
10186 | activate: [{ type: Output }],
|
10187 | deactivate: [{ type: Output }],
|
10188 | onMouseEnter: [{ type: HostListener, args: ['mouseenter',] }],
|
10189 | onMouseLeave: [{ type: HostListener, args: ['mouseleave',] }]
|
10190 | };
|
10191 |
|
10192 | class HeatCellSeriesComponent {
|
10193 | constructor() {
|
10194 | this.tooltipDisabled = false;
|
10195 | this.animations = true;
|
10196 | this.select = new EventEmitter();
|
10197 | this.activate = new EventEmitter();
|
10198 | this.deactivate = new EventEmitter();
|
10199 | this.placementTypes = PlacementTypes;
|
10200 | this.styleTypes = StyleTypes;
|
10201 | }
|
10202 | ngOnInit() {
|
10203 | if (!this.tooltipText) {
|
10204 | this.tooltipText = this.getTooltipText;
|
10205 | }
|
10206 | }
|
10207 | ngOnChanges(changes) {
|
10208 | this.update();
|
10209 | }
|
10210 | update() {
|
10211 | this.cells = this.getCells();
|
10212 | }
|
10213 | getCells() {
|
10214 | const cells = [];
|
10215 | this.data.map(row => {
|
10216 | row.series.map(cell => {
|
10217 | const value = cell.value;
|
10218 | cell.series = row.name;
|
10219 | cells.push({
|
10220 | row,
|
10221 | cell,
|
10222 | x: this.xScale(row.name),
|
10223 | y: this.yScale(cell.name),
|
10224 | width: this.xScale.bandwidth(),
|
10225 | height: this.yScale.bandwidth(),
|
10226 | fill: this.colors.getColor(value),
|
10227 | data: value,
|
10228 | label: formatLabel(cell.name),
|
10229 | series: row.name
|
10230 | });
|
10231 | });
|
10232 | });
|
10233 | return cells;
|
10234 | }
|
10235 | getTooltipText({ label, data, series }) {
|
10236 | return `
|
10237 | <span class="tooltip-label">${escapeLabel(series)} • ${escapeLabel(label)}</span>
|
10238 | <span class="tooltip-val">${data.toLocaleString()}</span>
|
10239 | `;
|
10240 | }
|
10241 | trackBy(index, item) {
|
10242 | return item.label;
|
10243 | }
|
10244 | onClick(data) {
|
10245 | this.select.emit(data);
|
10246 | }
|
10247 | }
|
10248 | HeatCellSeriesComponent.decorators = [
|
10249 | { type: Component, args: [{
|
10250 | selector: 'g[ngx-charts-heat-map-cell-series]',
|
10251 | template: `
|
10252 | <svg:g
|
10253 | ngx-charts-heat-map-cell
|
10254 | *ngFor="let c of cells; trackBy: trackBy"
|
10255 | [x]="c.x"
|
10256 | [y]="c.y"
|
10257 | [width]="c.width"
|
10258 | [height]="c.height"
|
10259 | [fill]="c.fill"
|
10260 | [data]="c.data"
|
10261 | (select)="onClick(c.cell)"
|
10262 | (activate)="activate.emit(c.cell)"
|
10263 | (deactivate)="deactivate.emit(c.cell)"
|
10264 | [gradient]="gradient"
|
10265 | [animations]="animations"
|
10266 | ngx-tooltip
|
10267 | [tooltipDisabled]="tooltipDisabled"
|
10268 | [tooltipPlacement]="placementTypes.Top"
|
10269 | [tooltipType]="styleTypes.tooltip"
|
10270 | [tooltipTitle]="tooltipTemplate ? undefined : tooltipText(c)"
|
10271 | [tooltipTemplate]="tooltipTemplate"
|
10272 | [tooltipContext]="{ series: c.series, name: c.label, value: c.data }"
|
10273 | ></svg:g>
|
10274 | `,
|
10275 | changeDetection: ChangeDetectionStrategy.OnPush
|
10276 | },] }
|
10277 | ];
|
10278 | HeatCellSeriesComponent.propDecorators = {
|
10279 | data: [{ type: Input }],
|
10280 | colors: [{ type: Input }],
|
10281 | xScale: [{ type: Input }],
|
10282 | yScale: [{ type: Input }],
|
10283 | gradient: [{ type: Input }],
|
10284 | tooltipDisabled: [{ type: Input }],
|
10285 | tooltipText: [{ type: Input }],
|
10286 | tooltipTemplate: [{ type: Input }],
|
10287 | animations: [{ type: Input }],
|
10288 | select: [{ type: Output }],
|
10289 | activate: [{ type: Output }],
|
10290 | deactivate: [{ type: Output }]
|
10291 | };
|
10292 |
|
10293 | class HeatMapComponent extends BaseChartComponent {
|
10294 | constructor() {
|
10295 | super(...arguments);
|
10296 | this.legendTitle = 'Legend';
|
10297 | this.legendPosition = LegendPosition.Right;
|
10298 | this.innerPadding = 8;
|
10299 | this.trimXAxisTicks = true;
|
10300 | this.trimYAxisTicks = true;
|
10301 | this.rotateXAxisTicks = true;
|
10302 | this.maxXAxisTickLength = 16;
|
10303 | this.maxYAxisTickLength = 16;
|
10304 | this.tooltipDisabled = false;
|
10305 | this.activeEntries = [];
|
10306 | this.activate = new EventEmitter();
|
10307 | this.deactivate = new EventEmitter();
|
10308 | this.margin = [10, 20, 10, 20];
|
10309 | this.xAxisHeight = 0;
|
10310 | this.yAxisWidth = 0;
|
10311 | this.scaleType = ScaleType.Linear;
|
10312 | }
|
10313 | update() {
|
10314 | super.update();
|
10315 | this.formatDates();
|
10316 | this.xDomain = this.getXDomain();
|
10317 | this.yDomain = this.getYDomain();
|
10318 | this.valueDomain = this.getValueDomain();
|
10319 | this.scaleType = getScaleType(this.valueDomain, false);
|
10320 | this.dims = calculateViewDimensions({
|
10321 | width: this.width,
|
10322 | height: this.height,
|
10323 | margins: this.margin,
|
10324 | showXAxis: this.xAxis,
|
10325 | showYAxis: this.yAxis,
|
10326 | xAxisHeight: this.xAxisHeight,
|
10327 | yAxisWidth: this.yAxisWidth,
|
10328 | showXLabel: this.showXAxisLabel,
|
10329 | showYLabel: this.showYAxisLabel,
|
10330 | showLegend: this.legend,
|
10331 | legendType: this.scaleType,
|
10332 | legendPosition: this.legendPosition
|
10333 | });
|
10334 | if (this.scaleType === ScaleType.Linear) {
|
10335 | let min = this.min;
|
10336 | let max = this.max;
|
10337 | if (!this.min) {
|
10338 | min = Math.min(0, ...this.valueDomain);
|
10339 | }
|
10340 | if (!this.max) {
|
10341 | max = Math.max(...this.valueDomain);
|
10342 | }
|
10343 | this.valueDomain = [min, max];
|
10344 | }
|
10345 | this.xScale = this.getXScale();
|
10346 | this.yScale = this.getYScale();
|
10347 | this.setColors();
|
10348 | this.legendOptions = this.getLegendOptions();
|
10349 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
10350 | this.rects = this.getRects();
|
10351 | }
|
10352 | getXDomain() {
|
10353 | const domain = [];
|
10354 | for (const group of this.results) {
|
10355 | if (!domain.includes(group.name)) {
|
10356 | domain.push(group.name);
|
10357 | }
|
10358 | }
|
10359 | return domain;
|
10360 | }
|
10361 | getYDomain() {
|
10362 | const domain = [];
|
10363 | for (const group of this.results) {
|
10364 | for (const d of group.series) {
|
10365 | if (!domain.includes(d.name)) {
|
10366 | domain.push(d.name);
|
10367 | }
|
10368 | }
|
10369 | }
|
10370 | return domain;
|
10371 | }
|
10372 | getValueDomain() {
|
10373 | const domain = [];
|
10374 | for (const group of this.results) {
|
10375 | for (const d of group.series) {
|
10376 | if (!domain.includes(d.value)) {
|
10377 | domain.push(d.value);
|
10378 | }
|
10379 | }
|
10380 | }
|
10381 | return domain;
|
10382 | }
|
10383 | |
10384 |
|
10385 |
|
10386 |
|
10387 |
|
10388 |
|
10389 |
|
10390 |
|
10391 |
|
10392 |
|
10393 | getDimension(value, index = 0, N, L) {
|
10394 | if (typeof value === 'string') {
|
10395 | value = value
|
10396 | .replace('[', '')
|
10397 | .replace(']', '')
|
10398 | .replace('px', '')
|
10399 |
|
10400 | .replace("'", '');
|
10401 | if (value.includes(',')) {
|
10402 | value = value.split(',');
|
10403 | }
|
10404 | }
|
10405 | if (Array.isArray(value) && typeof index === 'number') {
|
10406 | return this.getDimension(value[index], null, N, L);
|
10407 | }
|
10408 | if (typeof value === 'string' && value.includes('%')) {
|
10409 | return +value.replace('%', '') / 100;
|
10410 | }
|
10411 | return N / (L / +value + 1);
|
10412 | }
|
10413 | getXScale() {
|
10414 | const f = this.getDimension(this.innerPadding, 0, this.xDomain.length, this.dims.width);
|
10415 | return scaleBand().rangeRound([0, this.dims.width]).domain(this.xDomain).paddingInner(f);
|
10416 | }
|
10417 | getYScale() {
|
10418 | const f = this.getDimension(this.innerPadding, 1, this.yDomain.length, this.dims.height);
|
10419 | return scaleBand().rangeRound([this.dims.height, 0]).domain(this.yDomain).paddingInner(f);
|
10420 | }
|
10421 | getRects() {
|
10422 | const rects = [];
|
10423 | this.xDomain.map(xVal => {
|
10424 | this.yDomain.map(yVal => {
|
10425 | rects.push({
|
10426 | x: this.xScale(xVal),
|
10427 | y: this.yScale(yVal),
|
10428 | rx: 3,
|
10429 | width: this.xScale.bandwidth(),
|
10430 | height: this.yScale.bandwidth(),
|
10431 | fill: 'rgba(200,200,200,0.03)'
|
10432 | });
|
10433 | });
|
10434 | });
|
10435 | return rects;
|
10436 | }
|
10437 | onClick(data) {
|
10438 | this.select.emit(data);
|
10439 | }
|
10440 | setColors() {
|
10441 | this.colors = new ColorHelper(this.scheme, this.scaleType, this.valueDomain);
|
10442 | }
|
10443 | getLegendOptions() {
|
10444 | return {
|
10445 | scaleType: this.scaleType,
|
10446 | domain: this.valueDomain,
|
10447 | colors: this.scaleType === ScaleType.Ordinal ? this.colors : this.colors.scale,
|
10448 | title: this.scaleType === ScaleType.Ordinal ? this.legendTitle : undefined,
|
10449 | position: this.legendPosition
|
10450 | };
|
10451 | }
|
10452 | updateYAxisWidth({ width }) {
|
10453 | this.yAxisWidth = width;
|
10454 | this.update();
|
10455 | }
|
10456 | updateXAxisHeight({ height }) {
|
10457 | this.xAxisHeight = height;
|
10458 | this.update();
|
10459 | }
|
10460 | onActivate(event, group, fromLegend = false) {
|
10461 | const item = Object.assign({}, event);
|
10462 | if (group) {
|
10463 | item.series = group.name;
|
10464 | }
|
10465 | const items = this.results
|
10466 | .map(g => g.series)
|
10467 | .flat()
|
10468 | .filter(i => {
|
10469 | if (fromLegend) {
|
10470 | return i.label === item.name;
|
10471 | }
|
10472 | else {
|
10473 | return i.name === item.name && i.series === item.series;
|
10474 | }
|
10475 | });
|
10476 | this.activeEntries = [...items];
|
10477 | this.activate.emit({ value: item, entries: this.activeEntries });
|
10478 | }
|
10479 | onDeactivate(event, group, fromLegend = false) {
|
10480 | const item = Object.assign({}, event);
|
10481 | if (group) {
|
10482 | item.series = group.name;
|
10483 | }
|
10484 | this.activeEntries = this.activeEntries.filter(i => {
|
10485 | if (fromLegend) {
|
10486 | return i.label !== item.name;
|
10487 | }
|
10488 | else {
|
10489 | return !(i.name === item.name && i.series === item.series);
|
10490 | }
|
10491 | });
|
10492 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
10493 | }
|
10494 | }
|
10495 | HeatMapComponent.decorators = [
|
10496 | { type: Component, args: [{
|
10497 | selector: 'ngx-charts-heat-map',
|
10498 | template: `
|
10499 | <ngx-charts-chart
|
10500 | [view]="[width, height]"
|
10501 | [showLegend]="legend"
|
10502 | [animations]="animations"
|
10503 | [legendOptions]="legendOptions"
|
10504 | (legendLabelClick)="onClick($event)"
|
10505 | >
|
10506 | <svg:g [attr.transform]="transform" class="heat-map chart">
|
10507 | <svg:g
|
10508 | ngx-charts-x-axis
|
10509 | *ngIf="xAxis"
|
10510 | [xScale]="xScale"
|
10511 | [dims]="dims"
|
10512 | [showLabel]="showXAxisLabel"
|
10513 | [labelText]="xAxisLabel"
|
10514 | [trimTicks]="trimXAxisTicks"
|
10515 | [rotateTicks]="rotateXAxisTicks"
|
10516 | [maxTickLength]="maxXAxisTickLength"
|
10517 | [tickFormatting]="xAxisTickFormatting"
|
10518 | [ticks]="xAxisTicks"
|
10519 | (dimensionsChanged)="updateXAxisHeight($event)"
|
10520 | ></svg:g>
|
10521 | <svg:g
|
10522 | ngx-charts-y-axis
|
10523 | *ngIf="yAxis"
|
10524 | [yScale]="yScale"
|
10525 | [dims]="dims"
|
10526 | [showLabel]="showYAxisLabel"
|
10527 | [labelText]="yAxisLabel"
|
10528 | [trimTicks]="trimYAxisTicks"
|
10529 | [maxTickLength]="maxYAxisTickLength"
|
10530 | [tickFormatting]="yAxisTickFormatting"
|
10531 | [ticks]="yAxisTicks"
|
10532 | (dimensionsChanged)="updateYAxisWidth($event)"
|
10533 | ></svg:g>
|
10534 | <svg:rect
|
10535 | *ngFor="let rect of rects"
|
10536 | [attr.x]="rect.x"
|
10537 | [attr.y]="rect.y"
|
10538 | [attr.rx]="rect.rx"
|
10539 | [attr.width]="rect.width"
|
10540 | [attr.height]="rect.height"
|
10541 | [attr.fill]="rect.fill"
|
10542 | />
|
10543 | <svg:g
|
10544 | ngx-charts-heat-map-cell-series
|
10545 | [xScale]="xScale"
|
10546 | [yScale]="yScale"
|
10547 | [colors]="colors"
|
10548 | [data]="results"
|
10549 | [gradient]="gradient"
|
10550 | [animations]="animations"
|
10551 | [tooltipDisabled]="tooltipDisabled"
|
10552 | [tooltipTemplate]="tooltipTemplate"
|
10553 | [tooltipText]="tooltipText"
|
10554 | (select)="onClick($event)"
|
10555 | (activate)="onActivate($event, undefined)"
|
10556 | (deactivate)="onDeactivate($event, undefined)"
|
10557 | />
|
10558 | </svg:g>
|
10559 | </ngx-charts-chart>
|
10560 | `,
|
10561 | changeDetection: ChangeDetectionStrategy.OnPush,
|
10562 | encapsulation: ViewEncapsulation.None,
|
10563 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
10564 | },] }
|
10565 | ];
|
10566 | HeatMapComponent.propDecorators = {
|
10567 | legend: [{ type: Input }],
|
10568 | legendTitle: [{ type: Input }],
|
10569 | legendPosition: [{ type: Input }],
|
10570 | xAxis: [{ type: Input }],
|
10571 | yAxis: [{ type: Input }],
|
10572 | showXAxisLabel: [{ type: Input }],
|
10573 | showYAxisLabel: [{ type: Input }],
|
10574 | xAxisLabel: [{ type: Input }],
|
10575 | yAxisLabel: [{ type: Input }],
|
10576 | gradient: [{ type: Input }],
|
10577 | innerPadding: [{ type: Input }],
|
10578 | trimXAxisTicks: [{ type: Input }],
|
10579 | trimYAxisTicks: [{ type: Input }],
|
10580 | rotateXAxisTicks: [{ type: Input }],
|
10581 | maxXAxisTickLength: [{ type: Input }],
|
10582 | maxYAxisTickLength: [{ type: Input }],
|
10583 | xAxisTickFormatting: [{ type: Input }],
|
10584 | yAxisTickFormatting: [{ type: Input }],
|
10585 | xAxisTicks: [{ type: Input }],
|
10586 | yAxisTicks: [{ type: Input }],
|
10587 | tooltipDisabled: [{ type: Input }],
|
10588 | tooltipText: [{ type: Input }],
|
10589 | min: [{ type: Input }],
|
10590 | max: [{ type: Input }],
|
10591 | activeEntries: [{ type: Input }],
|
10592 | activate: [{ type: Output }],
|
10593 | deactivate: [{ type: Output }],
|
10594 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
10595 | };
|
10596 |
|
10597 | class HeatMapModule {
|
10598 | }
|
10599 | HeatMapModule.decorators = [
|
10600 | { type: NgModule, args: [{
|
10601 | imports: [ChartCommonModule],
|
10602 | declarations: [HeatMapCellComponent, HeatCellSeriesComponent, HeatMapComponent],
|
10603 | exports: [HeatMapCellComponent, HeatCellSeriesComponent, HeatMapComponent]
|
10604 | },] }
|
10605 | ];
|
10606 |
|
10607 | class LineComponent {
|
10608 | constructor(element) {
|
10609 | this.element = element;
|
10610 | this.fill = 'none';
|
10611 | this.animations = true;
|
10612 |
|
10613 | this.initialized = false;
|
10614 | }
|
10615 | ngOnChanges(changes) {
|
10616 | if (!this.initialized) {
|
10617 | this.initialized = true;
|
10618 | this.initialPath = this.path;
|
10619 | }
|
10620 | else {
|
10621 | this.updatePathEl();
|
10622 | }
|
10623 | }
|
10624 | updatePathEl() {
|
10625 | const node = select(this.element.nativeElement).select('.line');
|
10626 | if (this.animations) {
|
10627 | node.transition().duration(750).attr('d', this.path);
|
10628 | }
|
10629 | else {
|
10630 | node.attr('d', this.path);
|
10631 | }
|
10632 | }
|
10633 | }
|
10634 | LineComponent.decorators = [
|
10635 | { type: Component, args: [{
|
10636 | selector: 'g[ngx-charts-line]',
|
10637 | template: `
|
10638 | <svg:path
|
10639 | [@animationState]="'active'"
|
10640 | class="line"
|
10641 | [attr.d]="initialPath"
|
10642 | [attr.fill]="fill"
|
10643 | [attr.stroke]="stroke"
|
10644 | stroke-width="1.5px"
|
10645 | />
|
10646 | `,
|
10647 | changeDetection: ChangeDetectionStrategy.OnPush,
|
10648 | animations: [
|
10649 | trigger('animationState', [
|
10650 | transition(':enter', [
|
10651 | style({
|
10652 | strokeDasharray: 2000,
|
10653 | strokeDashoffset: 2000
|
10654 | }),
|
10655 | animate(1000, style({
|
10656 | strokeDashoffset: 0
|
10657 | }))
|
10658 | ])
|
10659 | ])
|
10660 | ]
|
10661 | },] }
|
10662 | ];
|
10663 | LineComponent.ctorParameters = () => [
|
10664 | { type: ElementRef }
|
10665 | ];
|
10666 | LineComponent.propDecorators = {
|
10667 | path: [{ type: Input }],
|
10668 | stroke: [{ type: Input }],
|
10669 | data: [{ type: Input }],
|
10670 | fill: [{ type: Input }],
|
10671 | animations: [{ type: Input }]
|
10672 | };
|
10673 |
|
10674 | class LineChartComponent extends BaseChartComponent {
|
10675 | constructor() {
|
10676 | super(...arguments);
|
10677 | this.legendTitle = 'Legend';
|
10678 | this.legendPosition = LegendPosition.Right;
|
10679 | this.showGridLines = true;
|
10680 | this.curve = curveLinear;
|
10681 | this.activeEntries = [];
|
10682 | this.trimXAxisTicks = true;
|
10683 | this.trimYAxisTicks = true;
|
10684 | this.rotateXAxisTicks = true;
|
10685 | this.maxXAxisTickLength = 16;
|
10686 | this.maxYAxisTickLength = 16;
|
10687 | this.roundDomains = false;
|
10688 | this.tooltipDisabled = false;
|
10689 | this.showRefLines = false;
|
10690 | this.showRefLabels = true;
|
10691 | this.activate = new EventEmitter();
|
10692 | this.deactivate = new EventEmitter();
|
10693 | this.margin = [10, 20, 10, 20];
|
10694 | this.xAxisHeight = 0;
|
10695 | this.yAxisWidth = 0;
|
10696 | this.timelineHeight = 50;
|
10697 | this.timelinePadding = 10;
|
10698 | }
|
10699 | update() {
|
10700 | super.update();
|
10701 | this.dims = calculateViewDimensions({
|
10702 | width: this.width,
|
10703 | height: this.height,
|
10704 | margins: this.margin,
|
10705 | showXAxis: this.xAxis,
|
10706 | showYAxis: this.yAxis,
|
10707 | xAxisHeight: this.xAxisHeight,
|
10708 | yAxisWidth: this.yAxisWidth,
|
10709 | showXLabel: this.showXAxisLabel,
|
10710 | showYLabel: this.showYAxisLabel,
|
10711 | showLegend: this.legend,
|
10712 | legendType: this.schemeType,
|
10713 | legendPosition: this.legendPosition
|
10714 | });
|
10715 | if (this.timeline) {
|
10716 | this.dims.height -= this.timelineHeight + this.margin[2] + this.timelinePadding;
|
10717 | }
|
10718 | this.xDomain = this.getXDomain();
|
10719 | if (this.filteredDomain) {
|
10720 | this.xDomain = this.filteredDomain;
|
10721 | }
|
10722 | this.yDomain = this.getYDomain();
|
10723 | this.seriesDomain = this.getSeriesDomain();
|
10724 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
10725 | this.yScale = this.getYScale(this.yDomain, this.dims.height);
|
10726 | this.updateTimeline();
|
10727 | this.setColors();
|
10728 | this.legendOptions = this.getLegendOptions();
|
10729 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
10730 | this.clipPathId = 'clip' + id().toString();
|
10731 | this.clipPath = `url(#${this.clipPathId})`;
|
10732 | }
|
10733 | updateTimeline() {
|
10734 | if (this.timeline) {
|
10735 | this.timelineWidth = this.dims.width;
|
10736 | this.timelineXDomain = this.getXDomain();
|
10737 | this.timelineXScale = this.getXScale(this.timelineXDomain, this.timelineWidth);
|
10738 | this.timelineYScale = this.getYScale(this.yDomain, this.timelineHeight);
|
10739 | this.timelineTransform = `translate(${this.dims.xOffset}, ${-this.margin[2]})`;
|
10740 | }
|
10741 | }
|
10742 | getXDomain() {
|
10743 | let values = getUniqueXDomainValues(this.results);
|
10744 | this.scaleType = getScaleType(values);
|
10745 | let domain = [];
|
10746 | if (this.scaleType === ScaleType.Linear) {
|
10747 | values = values.map(v => Number(v));
|
10748 | }
|
10749 | let min;
|
10750 | let max;
|
10751 | if (this.scaleType === ScaleType.Time || this.scaleType === ScaleType.Linear) {
|
10752 | min = this.xScaleMin ? this.xScaleMin : Math.min(...values);
|
10753 | max = this.xScaleMax ? this.xScaleMax : Math.max(...values);
|
10754 | }
|
10755 | if (this.scaleType === ScaleType.Time) {
|
10756 | domain = [new Date(min), new Date(max)];
|
10757 | this.xSet = [...values].sort((a, b) => {
|
10758 | const aDate = a.getTime();
|
10759 | const bDate = b.getTime();
|
10760 | if (aDate > bDate)
|
10761 | return 1;
|
10762 | if (bDate > aDate)
|
10763 | return -1;
|
10764 | return 0;
|
10765 | });
|
10766 | }
|
10767 | else if (this.scaleType === ScaleType.Linear) {
|
10768 | domain = [min, max];
|
10769 |
|
10770 | this.xSet = [...values].sort((a, b) => a - b);
|
10771 | }
|
10772 | else {
|
10773 | domain = values;
|
10774 | this.xSet = values;
|
10775 | }
|
10776 | return domain;
|
10777 | }
|
10778 | getYDomain() {
|
10779 | const domain = [];
|
10780 | for (const results of this.results) {
|
10781 | for (const d of results.series) {
|
10782 | if (domain.indexOf(d.value) < 0) {
|
10783 | domain.push(d.value);
|
10784 | }
|
10785 | if (d.min !== undefined) {
|
10786 | this.hasRange = true;
|
10787 | if (domain.indexOf(d.min) < 0) {
|
10788 | domain.push(d.min);
|
10789 | }
|
10790 | }
|
10791 | if (d.max !== undefined) {
|
10792 | this.hasRange = true;
|
10793 | if (domain.indexOf(d.max) < 0) {
|
10794 | domain.push(d.max);
|
10795 | }
|
10796 | }
|
10797 | }
|
10798 | }
|
10799 | const values = [...domain];
|
10800 | if (!this.autoScale) {
|
10801 | values.push(0);
|
10802 | }
|
10803 | const min = this.yScaleMin ? this.yScaleMin : Math.min(...values);
|
10804 | const max = this.yScaleMax ? this.yScaleMax : Math.max(...values);
|
10805 | return [min, max];
|
10806 | }
|
10807 | getSeriesDomain() {
|
10808 | return this.results.map(d => d.name);
|
10809 | }
|
10810 | getXScale(domain, width) {
|
10811 | let scale;
|
10812 | if (this.scaleType === ScaleType.Time) {
|
10813 | scale = scaleTime().range([0, width]).domain(domain);
|
10814 | }
|
10815 | else if (this.scaleType === ScaleType.Linear) {
|
10816 | scale = scaleLinear().range([0, width]).domain(domain);
|
10817 | if (this.roundDomains) {
|
10818 | scale = scale.nice();
|
10819 | }
|
10820 | }
|
10821 | else if (this.scaleType === ScaleType.Ordinal) {
|
10822 | scale = scalePoint().range([0, width]).padding(0.1).domain(domain);
|
10823 | }
|
10824 | return scale;
|
10825 | }
|
10826 | getYScale(domain, height) {
|
10827 | const scale = scaleLinear().range([height, 0]).domain(domain);
|
10828 | return this.roundDomains ? scale.nice() : scale;
|
10829 | }
|
10830 | updateDomain(domain) {
|
10831 | this.filteredDomain = domain;
|
10832 | this.xDomain = this.filteredDomain;
|
10833 | this.xScale = this.getXScale(this.xDomain, this.dims.width);
|
10834 | }
|
10835 | updateHoveredVertical(item) {
|
10836 | this.hoveredVertical = item.value;
|
10837 | this.deactivateAll();
|
10838 | }
|
10839 | hideCircles() {
|
10840 | this.hoveredVertical = null;
|
10841 | this.deactivateAll();
|
10842 | }
|
10843 | onClick(data) {
|
10844 | this.select.emit(data);
|
10845 | }
|
10846 | trackBy(index, item) {
|
10847 | return `${item.name}`;
|
10848 | }
|
10849 | setColors() {
|
10850 | let domain;
|
10851 | if (this.schemeType === ScaleType.Ordinal) {
|
10852 | domain = this.seriesDomain;
|
10853 | }
|
10854 | else {
|
10855 | domain = this.yDomain;
|
10856 | }
|
10857 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
10858 | }
|
10859 | getLegendOptions() {
|
10860 | const opts = {
|
10861 | scaleType: this.schemeType,
|
10862 | colors: undefined,
|
10863 | domain: [],
|
10864 | title: undefined,
|
10865 | position: this.legendPosition
|
10866 | };
|
10867 | if (opts.scaleType === ScaleType.Ordinal) {
|
10868 | opts.domain = this.seriesDomain;
|
10869 | opts.colors = this.colors;
|
10870 | opts.title = this.legendTitle;
|
10871 | }
|
10872 | else {
|
10873 | opts.domain = this.yDomain;
|
10874 | opts.colors = this.colors.scale;
|
10875 | }
|
10876 | return opts;
|
10877 | }
|
10878 | updateYAxisWidth({ width }) {
|
10879 | this.yAxisWidth = width;
|
10880 | this.update();
|
10881 | }
|
10882 | updateXAxisHeight({ height }) {
|
10883 | this.xAxisHeight = height;
|
10884 | this.update();
|
10885 | }
|
10886 | onActivate(item) {
|
10887 | this.deactivateAll();
|
10888 | const idx = this.activeEntries.findIndex(d => {
|
10889 | return d.name === item.name && d.value === item.value;
|
10890 | });
|
10891 | if (idx > -1) {
|
10892 | return;
|
10893 | }
|
10894 | this.activeEntries = [item];
|
10895 | this.activate.emit({ value: item, entries: this.activeEntries });
|
10896 | }
|
10897 | onDeactivate(item) {
|
10898 | const idx = this.activeEntries.findIndex(d => {
|
10899 | return d.name === item.name && d.value === item.value;
|
10900 | });
|
10901 | this.activeEntries.splice(idx, 1);
|
10902 | this.activeEntries = [...this.activeEntries];
|
10903 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
10904 | }
|
10905 | deactivateAll() {
|
10906 | this.activeEntries = [...this.activeEntries];
|
10907 | for (const entry of this.activeEntries) {
|
10908 | this.deactivate.emit({ value: entry, entries: [] });
|
10909 | }
|
10910 | this.activeEntries = [];
|
10911 | }
|
10912 | }
|
10913 | LineChartComponent.decorators = [
|
10914 | { type: Component, args: [{
|
10915 | selector: 'ngx-charts-line-chart',
|
10916 | template: `
|
10917 | <ngx-charts-chart
|
10918 | [view]="[width, height]"
|
10919 | [showLegend]="legend"
|
10920 | [legendOptions]="legendOptions"
|
10921 | [activeEntries]="activeEntries"
|
10922 | [animations]="animations"
|
10923 | (legendLabelClick)="onClick($event)"
|
10924 | (legendLabelActivate)="onActivate($event)"
|
10925 | (legendLabelDeactivate)="onDeactivate($event)"
|
10926 | >
|
10927 | <svg:defs>
|
10928 | <svg:clipPath [attr.id]="clipPathId">
|
10929 | <svg:rect
|
10930 | [attr.width]="dims.width + 10"
|
10931 | [attr.height]="dims.height + 10"
|
10932 | [attr.transform]="'translate(-5, -5)'"
|
10933 | />
|
10934 | </svg:clipPath>
|
10935 | </svg:defs>
|
10936 | <svg:g [attr.transform]="transform" class="line-chart chart">
|
10937 | <svg:g
|
10938 | ngx-charts-x-axis
|
10939 | *ngIf="xAxis"
|
10940 | [xScale]="xScale"
|
10941 | [dims]="dims"
|
10942 | [showGridLines]="showGridLines"
|
10943 | [showLabel]="showXAxisLabel"
|
10944 | [labelText]="xAxisLabel"
|
10945 | [trimTicks]="trimXAxisTicks"
|
10946 | [rotateTicks]="rotateXAxisTicks"
|
10947 | [maxTickLength]="maxXAxisTickLength"
|
10948 | [tickFormatting]="xAxisTickFormatting"
|
10949 | [ticks]="xAxisTicks"
|
10950 | (dimensionsChanged)="updateXAxisHeight($event)"
|
10951 | ></svg:g>
|
10952 | <svg:g
|
10953 | ngx-charts-y-axis
|
10954 | *ngIf="yAxis"
|
10955 | [yScale]="yScale"
|
10956 | [dims]="dims"
|
10957 | [showGridLines]="showGridLines"
|
10958 | [showLabel]="showYAxisLabel"
|
10959 | [labelText]="yAxisLabel"
|
10960 | [trimTicks]="trimYAxisTicks"
|
10961 | [maxTickLength]="maxYAxisTickLength"
|
10962 | [tickFormatting]="yAxisTickFormatting"
|
10963 | [ticks]="yAxisTicks"
|
10964 | [referenceLines]="referenceLines"
|
10965 | [showRefLines]="showRefLines"
|
10966 | [showRefLabels]="showRefLabels"
|
10967 | (dimensionsChanged)="updateYAxisWidth($event)"
|
10968 | ></svg:g>
|
10969 | <svg:g [attr.clip-path]="clipPath">
|
10970 | <svg:g *ngFor="let series of results; trackBy: trackBy" [@animationState]="'active'">
|
10971 | <svg:g
|
10972 | ngx-charts-line-series
|
10973 | [xScale]="xScale"
|
10974 | [yScale]="yScale"
|
10975 | [colors]="colors"
|
10976 | [data]="series"
|
10977 | [activeEntries]="activeEntries"
|
10978 | [scaleType]="scaleType"
|
10979 | [curve]="curve"
|
10980 | [rangeFillOpacity]="rangeFillOpacity"
|
10981 | [hasRange]="hasRange"
|
10982 | [animations]="animations"
|
10983 | />
|
10984 | </svg:g>
|
10985 |
|
10986 | <svg:g *ngIf="!tooltipDisabled" (mouseleave)="hideCircles()">
|
10987 | <svg:g
|
10988 | ngx-charts-tooltip-area
|
10989 | [dims]="dims"
|
10990 | [xSet]="xSet"
|
10991 | [xScale]="xScale"
|
10992 | [yScale]="yScale"
|
10993 | [results]="results"
|
10994 | [colors]="colors"
|
10995 | [tooltipDisabled]="tooltipDisabled"
|
10996 | [tooltipTemplate]="seriesTooltipTemplate"
|
10997 | (hover)="updateHoveredVertical($event)"
|
10998 | />
|
10999 |
|
11000 | <svg:g *ngFor="let series of results">
|
11001 | <svg:g
|
11002 | ngx-charts-circle-series
|
11003 | [xScale]="xScale"
|
11004 | [yScale]="yScale"
|
11005 | [colors]="colors"
|
11006 | [data]="series"
|
11007 | [scaleType]="scaleType"
|
11008 | [visibleValue]="hoveredVertical"
|
11009 | [activeEntries]="activeEntries"
|
11010 | [tooltipDisabled]="tooltipDisabled"
|
11011 | [tooltipTemplate]="tooltipTemplate"
|
11012 | (select)="onClick($event)"
|
11013 | (activate)="onActivate($event)"
|
11014 | (deactivate)="onDeactivate($event)"
|
11015 | />
|
11016 | </svg:g>
|
11017 | </svg:g>
|
11018 | </svg:g>
|
11019 | </svg:g>
|
11020 | <svg:g
|
11021 | ngx-charts-timeline
|
11022 | *ngIf="timeline && scaleType != 'ordinal'"
|
11023 | [attr.transform]="timelineTransform"
|
11024 | [results]="results"
|
11025 | [view]="[timelineWidth, height]"
|
11026 | [height]="timelineHeight"
|
11027 | [scheme]="scheme"
|
11028 | [customColors]="customColors"
|
11029 | [scaleType]="scaleType"
|
11030 | [legend]="legend"
|
11031 | (onDomainChange)="updateDomain($event)"
|
11032 | >
|
11033 | <svg:g *ngFor="let series of results; trackBy: trackBy">
|
11034 | <svg:g
|
11035 | ngx-charts-line-series
|
11036 | [xScale]="timelineXScale"
|
11037 | [yScale]="timelineYScale"
|
11038 | [colors]="colors"
|
11039 | [data]="series"
|
11040 | [scaleType]="scaleType"
|
11041 | [curve]="curve"
|
11042 | [hasRange]="hasRange"
|
11043 | [animations]="animations"
|
11044 | />
|
11045 | </svg:g>
|
11046 | </svg:g>
|
11047 | </ngx-charts-chart>
|
11048 | `,
|
11049 | encapsulation: ViewEncapsulation.None,
|
11050 | changeDetection: ChangeDetectionStrategy.OnPush,
|
11051 | animations: [
|
11052 | trigger('animationState', [
|
11053 | transition(':leave', [
|
11054 | style({
|
11055 | opacity: 1
|
11056 | }),
|
11057 | animate(500, style({
|
11058 | opacity: 0
|
11059 | }))
|
11060 | ])
|
11061 | ])
|
11062 | ],
|
11063 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
11064 | },] }
|
11065 | ];
|
11066 | LineChartComponent.propDecorators = {
|
11067 | legend: [{ type: Input }],
|
11068 | legendTitle: [{ type: Input }],
|
11069 | legendPosition: [{ type: Input }],
|
11070 | xAxis: [{ type: Input }],
|
11071 | yAxis: [{ type: Input }],
|
11072 | showXAxisLabel: [{ type: Input }],
|
11073 | showYAxisLabel: [{ type: Input }],
|
11074 | xAxisLabel: [{ type: Input }],
|
11075 | yAxisLabel: [{ type: Input }],
|
11076 | autoScale: [{ type: Input }],
|
11077 | timeline: [{ type: Input }],
|
11078 | gradient: [{ type: Input }],
|
11079 | showGridLines: [{ type: Input }],
|
11080 | curve: [{ type: Input }],
|
11081 | activeEntries: [{ type: Input }],
|
11082 | schemeType: [{ type: Input }],
|
11083 | rangeFillOpacity: [{ type: Input }],
|
11084 | trimXAxisTicks: [{ type: Input }],
|
11085 | trimYAxisTicks: [{ type: Input }],
|
11086 | rotateXAxisTicks: [{ type: Input }],
|
11087 | maxXAxisTickLength: [{ type: Input }],
|
11088 | maxYAxisTickLength: [{ type: Input }],
|
11089 | xAxisTickFormatting: [{ type: Input }],
|
11090 | yAxisTickFormatting: [{ type: Input }],
|
11091 | xAxisTicks: [{ type: Input }],
|
11092 | yAxisTicks: [{ type: Input }],
|
11093 | roundDomains: [{ type: Input }],
|
11094 | tooltipDisabled: [{ type: Input }],
|
11095 | showRefLines: [{ type: Input }],
|
11096 | referenceLines: [{ type: Input }],
|
11097 | showRefLabels: [{ type: Input }],
|
11098 | xScaleMin: [{ type: Input }],
|
11099 | xScaleMax: [{ type: Input }],
|
11100 | yScaleMin: [{ type: Input }],
|
11101 | yScaleMax: [{ type: Input }],
|
11102 | activate: [{ type: Output }],
|
11103 | deactivate: [{ type: Output }],
|
11104 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
11105 | seriesTooltipTemplate: [{ type: ContentChild, args: ['seriesTooltipTemplate',] }],
|
11106 | hideCircles: [{ type: HostListener, args: ['mouseleave',] }]
|
11107 | };
|
11108 |
|
11109 | class LineSeriesComponent {
|
11110 | constructor() {
|
11111 | this.animations = true;
|
11112 | this.barOrientation = BarOrientation;
|
11113 | }
|
11114 | ngOnChanges(changes) {
|
11115 | this.update();
|
11116 | }
|
11117 | update() {
|
11118 | this.updateGradients();
|
11119 | const data = this.sortData(this.data.series);
|
11120 | const lineGen = this.getLineGenerator();
|
11121 | this.path = lineGen(data) || '';
|
11122 | const areaGen = this.getAreaGenerator();
|
11123 | this.areaPath = areaGen(data) || '';
|
11124 | if (this.hasRange) {
|
11125 | const range = this.getRangeGenerator();
|
11126 | this.outerPath = range(data) || '';
|
11127 | }
|
11128 | if (this.hasGradient) {
|
11129 | this.stroke = this.gradientUrl;
|
11130 | const values = this.data.series.map(d => d.value);
|
11131 | const max = Math.max(...values);
|
11132 | const min = Math.min(...values);
|
11133 | if (max === min) {
|
11134 | this.stroke = this.colors.getColor(max);
|
11135 | }
|
11136 | }
|
11137 | else {
|
11138 | this.stroke = this.colors.getColor(this.data.name);
|
11139 | }
|
11140 | }
|
11141 | getLineGenerator() {
|
11142 | return line()
|
11143 | .x(d => {
|
11144 | const label = d.name;
|
11145 | let value;
|
11146 | if (this.scaleType === ScaleType.Time) {
|
11147 | value = this.xScale(label);
|
11148 | }
|
11149 | else if (this.scaleType === ScaleType.Linear) {
|
11150 | value = this.xScale(Number(label));
|
11151 | }
|
11152 | else {
|
11153 | value = this.xScale(label);
|
11154 | }
|
11155 | return value;
|
11156 | })
|
11157 | .y(d => this.yScale(d.value))
|
11158 | .curve(this.curve);
|
11159 | }
|
11160 | getRangeGenerator() {
|
11161 | return area()
|
11162 | .x(d => {
|
11163 | const label = d.name;
|
11164 | let value;
|
11165 | if (this.scaleType === ScaleType.Time) {
|
11166 | value = this.xScale(label);
|
11167 | }
|
11168 | else if (this.scaleType === ScaleType.Linear) {
|
11169 | value = this.xScale(Number(label));
|
11170 | }
|
11171 | else {
|
11172 | value = this.xScale(label);
|
11173 | }
|
11174 | return value;
|
11175 | })
|
11176 | .y0(d => this.yScale(typeof d.min === 'number' ? d.min : d.value))
|
11177 | .y1(d => this.yScale(typeof d.max === 'number' ? d.max : d.value))
|
11178 | .curve(this.curve);
|
11179 | }
|
11180 | getAreaGenerator() {
|
11181 | const xProperty = d => {
|
11182 | const label = d.name;
|
11183 | return this.xScale(label);
|
11184 | };
|
11185 | return area()
|
11186 | .x(xProperty)
|
11187 | .y0(() => this.yScale.range()[0])
|
11188 | .y1(d => this.yScale(d.value))
|
11189 | .curve(this.curve);
|
11190 | }
|
11191 | sortData(data) {
|
11192 | if (this.scaleType === ScaleType.Linear) {
|
11193 | data = sortLinear(data, 'name');
|
11194 | }
|
11195 | else if (this.scaleType === ScaleType.Time) {
|
11196 | data = sortByTime(data, 'name');
|
11197 | }
|
11198 | else {
|
11199 | data = sortByDomain(data, 'name', 'asc', this.xScale.domain());
|
11200 | }
|
11201 | return data;
|
11202 | }
|
11203 | updateGradients() {
|
11204 | if (this.colors.scaleType === ScaleType.Linear) {
|
11205 | this.hasGradient = true;
|
11206 | this.gradientId = 'grad' + id().toString();
|
11207 | this.gradientUrl = `url(#${this.gradientId})`;
|
11208 | const values = this.data.series.map(d => d.value);
|
11209 | const max = Math.max(...values);
|
11210 | const min = Math.min(...values);
|
11211 | this.gradientStops = this.colors.getLinearGradientStops(max, min);
|
11212 | this.areaGradientStops = this.colors.getLinearGradientStops(max);
|
11213 | }
|
11214 | else {
|
11215 | this.hasGradient = false;
|
11216 | this.gradientStops = undefined;
|
11217 | this.areaGradientStops = undefined;
|
11218 | }
|
11219 | }
|
11220 | isActive(entry) {
|
11221 | if (!this.activeEntries)
|
11222 | return false;
|
11223 | const item = this.activeEntries.find(d => {
|
11224 | return entry.name === d.name;
|
11225 | });
|
11226 | return item !== undefined;
|
11227 | }
|
11228 | isInactive(entry) {
|
11229 | if (!this.activeEntries || this.activeEntries.length === 0)
|
11230 | return false;
|
11231 | const item = this.activeEntries.find(d => {
|
11232 | return entry.name === d.name;
|
11233 | });
|
11234 | return item === undefined;
|
11235 | }
|
11236 | }
|
11237 | LineSeriesComponent.decorators = [
|
11238 | { type: Component, args: [{
|
11239 | selector: 'g[ngx-charts-line-series]',
|
11240 | template: `
|
11241 | <svg:g>
|
11242 | <defs>
|
11243 | <svg:g
|
11244 | ngx-charts-svg-linear-gradient
|
11245 | *ngIf="hasGradient"
|
11246 | [orientation]="barOrientation.Vertical"
|
11247 | [name]="gradientId"
|
11248 | [stops]="gradientStops"
|
11249 | />
|
11250 | </defs>
|
11251 | <svg:g
|
11252 | ngx-charts-area
|
11253 | class="line-highlight"
|
11254 | [data]="data"
|
11255 | [path]="areaPath"
|
11256 | [fill]="hasGradient ? gradientUrl : colors.getColor(data.name)"
|
11257 | [opacity]="0.25"
|
11258 | [startOpacity]="0"
|
11259 | [gradient]="true"
|
11260 | [stops]="areaGradientStops"
|
11261 | [class.active]="isActive(data)"
|
11262 | [class.inactive]="isInactive(data)"
|
11263 | [animations]="animations"
|
11264 | />
|
11265 | <svg:g
|
11266 | ngx-charts-line
|
11267 | class="line-series"
|
11268 | [data]="data"
|
11269 | [path]="path"
|
11270 | [stroke]="stroke"
|
11271 | [animations]="animations"
|
11272 | [class.active]="isActive(data)"
|
11273 | [class.inactive]="isInactive(data)"
|
11274 | />
|
11275 | <svg:g
|
11276 | ngx-charts-area
|
11277 | *ngIf="hasRange"
|
11278 | class="line-series-range"
|
11279 | [data]="data"
|
11280 | [path]="outerPath"
|
11281 | [fill]="hasGradient ? gradientUrl : colors.getColor(data.name)"
|
11282 | [class.active]="isActive(data)"
|
11283 | [class.inactive]="isInactive(data)"
|
11284 | [opacity]="rangeFillOpacity"
|
11285 | [animations]="animations"
|
11286 | />
|
11287 | </svg:g>
|
11288 | `,
|
11289 | changeDetection: ChangeDetectionStrategy.OnPush
|
11290 | },] }
|
11291 | ];
|
11292 | LineSeriesComponent.propDecorators = {
|
11293 | data: [{ type: Input }],
|
11294 | xScale: [{ type: Input }],
|
11295 | yScale: [{ type: Input }],
|
11296 | colors: [{ type: Input }],
|
11297 | scaleType: [{ type: Input }],
|
11298 | curve: [{ type: Input }],
|
11299 | activeEntries: [{ type: Input }],
|
11300 | rangeFillOpacity: [{ type: Input }],
|
11301 | hasRange: [{ type: Input }],
|
11302 | animations: [{ type: Input }]
|
11303 | };
|
11304 |
|
11305 | class LineChartModule {
|
11306 | }
|
11307 | LineChartModule.decorators = [
|
11308 | { type: NgModule, args: [{
|
11309 | imports: [ChartCommonModule],
|
11310 | declarations: [LineComponent, LineChartComponent, LineSeriesComponent],
|
11311 | exports: [LineComponent, LineChartComponent, LineSeriesComponent]
|
11312 | },] }
|
11313 | ];
|
11314 |
|
11315 | const twoPI = 2 * Math.PI;
|
11316 | class PolarChartComponent extends BaseChartComponent {
|
11317 | constructor() {
|
11318 | super(...arguments);
|
11319 | this.legendTitle = 'Legend';
|
11320 | this.legendPosition = LegendPosition.Right;
|
11321 | this.showGridLines = true;
|
11322 | this.curve = curveCardinalClosed;
|
11323 | this.activeEntries = [];
|
11324 | this.rangeFillOpacity = 0.15;
|
11325 | this.trimYAxisTicks = true;
|
11326 | this.maxYAxisTickLength = 16;
|
11327 | this.roundDomains = false;
|
11328 | this.tooltipDisabled = false;
|
11329 | this.showSeriesOnHover = true;
|
11330 | this.gradient = false;
|
11331 | this.yAxisMinScale = 0;
|
11332 | this.labelTrim = true;
|
11333 | this.labelTrimSize = 10;
|
11334 | this.activate = new EventEmitter();
|
11335 | this.deactivate = new EventEmitter();
|
11336 |
|
11337 | this.margin = [10, 20, 10, 20];
|
11338 | this.xAxisHeight = 0;
|
11339 | this.yAxisWidth = 0;
|
11340 | this.orientation = Orientation;
|
11341 | }
|
11342 | update() {
|
11343 | super.update();
|
11344 | this.setDims();
|
11345 | this.setScales();
|
11346 | this.setColors();
|
11347 | this.legendOptions = this.getLegendOptions();
|
11348 | this.setTicks();
|
11349 | }
|
11350 | setDims() {
|
11351 | this.dims = calculateViewDimensions({
|
11352 | width: this.width,
|
11353 | height: this.height,
|
11354 | margins: this.margin,
|
11355 | showXAxis: this.xAxis,
|
11356 | showYAxis: this.yAxis,
|
11357 | xAxisHeight: this.xAxisHeight,
|
11358 | yAxisWidth: this.yAxisWidth,
|
11359 | showXLabel: this.showXAxisLabel,
|
11360 | showYLabel: this.showYAxisLabel,
|
11361 | showLegend: this.legend,
|
11362 | legendType: this.schemeType,
|
11363 | legendPosition: this.legendPosition
|
11364 | });
|
11365 | const halfWidth = Math.floor(this.dims.width / 2);
|
11366 | const halfHeight = Math.floor(this.dims.height / 2);
|
11367 | const outerRadius = (this.outerRadius = Math.min(halfHeight / 1.5, halfWidth / 1.5));
|
11368 | const yOffset = Math.max(0, halfHeight - outerRadius);
|
11369 | this.yAxisDims = Object.assign(Object.assign({}, this.dims), { width: halfWidth });
|
11370 | this.transform = `translate(${this.dims.xOffset}, ${this.margin[0]})`;
|
11371 | this.transformYAxis = `translate(0, ${yOffset})`;
|
11372 | this.labelOffset = this.dims.height + 40;
|
11373 | this.transformPlot = `translate(${halfWidth}, ${halfHeight})`;
|
11374 | }
|
11375 | setScales() {
|
11376 | const xValues = this.getXValues();
|
11377 | this.scaleType = getScaleType(xValues);
|
11378 | this.xDomain = this.filteredDomain || this.getXDomain(xValues);
|
11379 | this.yDomain = this.getYDomain();
|
11380 | this.seriesDomain = this.getSeriesDomain();
|
11381 | this.xScale = this.getXScale(this.xDomain, twoPI);
|
11382 | this.yScale = this.getYScale(this.yDomain, this.outerRadius);
|
11383 | this.yAxisScale = this.getYScale(this.yDomain.reverse(), this.outerRadius);
|
11384 | }
|
11385 | setTicks() {
|
11386 | let tickFormat;
|
11387 | if (this.xAxisTickFormatting) {
|
11388 | tickFormat = this.xAxisTickFormatting;
|
11389 | }
|
11390 | else if (this.xScale.tickFormat) {
|
11391 | tickFormat = this.xScale.tickFormat.apply(this.xScale, [5]);
|
11392 | }
|
11393 | else {
|
11394 | tickFormat = d => {
|
11395 | if (isDate(d)) {
|
11396 | return d.toLocaleDateString();
|
11397 | }
|
11398 | return d.toLocaleString();
|
11399 | };
|
11400 | }
|
11401 | const outerRadius = this.outerRadius;
|
11402 | const s = 1.1;
|
11403 | this.thetaTicks = this.xDomain.map(d => {
|
11404 | const startAngle = this.xScale(d);
|
11405 | const dd = s * outerRadius * (startAngle > Math.PI ? -1 : 1);
|
11406 | const label = tickFormat(d);
|
11407 | const startPos = [outerRadius * Math.sin(startAngle), -outerRadius * Math.cos(startAngle)];
|
11408 | const pos = [dd, s * startPos[1]];
|
11409 | return {
|
11410 | innerRadius: 0,
|
11411 | outerRadius,
|
11412 | startAngle,
|
11413 | endAngle: startAngle,
|
11414 | value: outerRadius,
|
11415 | label,
|
11416 | startPos,
|
11417 | pos
|
11418 | };
|
11419 | });
|
11420 | const minDistance = 10;
|
11421 |
|
11422 | for (let i = 0; i < this.thetaTicks.length - 1; i++) {
|
11423 | const a = this.thetaTicks[i];
|
11424 | for (let j = i + 1; j < this.thetaTicks.length; j++) {
|
11425 | const b = this.thetaTicks[j];
|
11426 |
|
11427 | if (b.pos[0] * a.pos[0] > 0) {
|
11428 |
|
11429 | const o = minDistance - Math.abs(b.pos[1] - a.pos[1]);
|
11430 | if (o > 0) {
|
11431 |
|
11432 | b.pos[1] += Math.sign(b.pos[0]) * o;
|
11433 | }
|
11434 | }
|
11435 | }
|
11436 | }
|
11437 | this.radiusTicks = this.yAxisScale.ticks(Math.floor(this.dims.height / 50)).map(d => this.yScale(d));
|
11438 | }
|
11439 | getXValues() {
|
11440 | const values = [];
|
11441 | for (const results of this.results) {
|
11442 | for (const d of results.series) {
|
11443 | if (!values.includes(d.name)) {
|
11444 | values.push(d.name);
|
11445 | }
|
11446 | }
|
11447 | }
|
11448 | return values;
|
11449 | }
|
11450 | getXDomain(values = this.getXValues()) {
|
11451 | if (this.scaleType === ScaleType.Time) {
|
11452 | const min = Math.min(...values);
|
11453 | const max = Math.max(...values);
|
11454 | return [min, max];
|
11455 | }
|
11456 | else if (this.scaleType === ScaleType.Linear) {
|
11457 | values = values.map(v => Number(v));
|
11458 | const min = Math.min(...values);
|
11459 | const max = Math.max(...values);
|
11460 | return [min, max];
|
11461 | }
|
11462 | return values;
|
11463 | }
|
11464 | getYValues() {
|
11465 | const domain = [];
|
11466 | for (const results of this.results) {
|
11467 | for (const d of results.series) {
|
11468 | if (domain.indexOf(d.value) < 0) {
|
11469 | domain.push(d.value);
|
11470 | }
|
11471 | if (d.min !== undefined) {
|
11472 | if (domain.indexOf(d.min) < 0) {
|
11473 | domain.push(d.min);
|
11474 | }
|
11475 | }
|
11476 | if (d.max !== undefined) {
|
11477 | if (domain.indexOf(d.max) < 0) {
|
11478 | domain.push(d.max);
|
11479 | }
|
11480 | }
|
11481 | }
|
11482 | }
|
11483 | return domain;
|
11484 | }
|
11485 | getYDomain(domain = this.getYValues()) {
|
11486 | let min = Math.min(...domain);
|
11487 | const max = Math.max(this.yAxisMinScale, ...domain);
|
11488 | min = Math.max(0, min);
|
11489 | if (!this.autoScale) {
|
11490 | min = Math.min(0, min);
|
11491 | }
|
11492 | return [min, max];
|
11493 | }
|
11494 | getSeriesDomain() {
|
11495 | return this.results.map(d => d.name);
|
11496 | }
|
11497 | getXScale(domain, width) {
|
11498 | switch (this.scaleType) {
|
11499 | case ScaleType.Time:
|
11500 | return scaleTime().range([0, width]).domain(domain);
|
11501 | case ScaleType.Linear:
|
11502 | const scale = scaleLinear().range([0, width]).domain(domain);
|
11503 | return this.roundDomains ? scale.nice() : scale;
|
11504 | default:
|
11505 | return scalePoint()
|
11506 | .range([0, width - twoPI / domain.length])
|
11507 | .padding(0)
|
11508 | .domain(domain);
|
11509 | }
|
11510 | }
|
11511 | getYScale(domain, height) {
|
11512 | const scale = scaleLinear().range([0, height]).domain(domain);
|
11513 | return this.roundDomains ? scale.nice() : scale;
|
11514 | }
|
11515 | onClick(data, series) {
|
11516 | if (series) {
|
11517 | data.series = series.name;
|
11518 | }
|
11519 | this.select.emit(data);
|
11520 | }
|
11521 | setColors() {
|
11522 | const domain = this.schemeType === ScaleType.Ordinal ? this.seriesDomain : this.yDomain.reverse();
|
11523 | this.colors = new ColorHelper(this.scheme, this.schemeType, domain, this.customColors);
|
11524 | }
|
11525 | getLegendOptions() {
|
11526 | if (this.schemeType === ScaleType.Ordinal) {
|
11527 | return {
|
11528 | scaleType: this.schemeType,
|
11529 | colors: this.colors,
|
11530 | domain: this.seriesDomain,
|
11531 | title: this.legendTitle,
|
11532 | position: this.legendPosition
|
11533 | };
|
11534 | }
|
11535 | return {
|
11536 | scaleType: this.schemeType,
|
11537 | colors: this.colors.scale,
|
11538 | domain: this.yDomain,
|
11539 | title: undefined,
|
11540 | position: this.legendPosition
|
11541 | };
|
11542 | }
|
11543 | updateYAxisWidth({ width }) {
|
11544 | this.yAxisWidth = width;
|
11545 | this.update();
|
11546 | }
|
11547 | updateXAxisHeight({ height }) {
|
11548 | this.xAxisHeight = height;
|
11549 | this.update();
|
11550 | }
|
11551 | onActivate(item) {
|
11552 | const idx = this.activeEntries.findIndex(d => {
|
11553 | return d.name === item.name && d.value === item.value;
|
11554 | });
|
11555 | if (idx > -1) {
|
11556 | return;
|
11557 | }
|
11558 | this.activeEntries = this.showSeriesOnHover ? [item, ...this.activeEntries] : this.activeEntries;
|
11559 | this.activate.emit({ value: item, entries: this.activeEntries });
|
11560 | }
|
11561 | onDeactivate(item) {
|
11562 | const idx = this.activeEntries.findIndex(d => {
|
11563 | return d.name === item.name && d.value === item.value;
|
11564 | });
|
11565 | this.activeEntries.splice(idx, 1);
|
11566 | this.activeEntries = [...this.activeEntries];
|
11567 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
11568 | }
|
11569 | deactivateAll() {
|
11570 | this.activeEntries = [...this.activeEntries];
|
11571 | for (const entry of this.activeEntries) {
|
11572 | this.deactivate.emit({ value: entry, entries: [] });
|
11573 | }
|
11574 | this.activeEntries = [];
|
11575 | }
|
11576 | trackBy(index, item) {
|
11577 | return `${item.name}`;
|
11578 | }
|
11579 | }
|
11580 | PolarChartComponent.decorators = [
|
11581 | { type: Component, args: [{
|
11582 | selector: 'ngx-charts-polar-chart',
|
11583 | template: `
|
11584 | <ngx-charts-chart
|
11585 | [view]="[width, height]"
|
11586 | [showLegend]="legend"
|
11587 | [legendOptions]="legendOptions"
|
11588 | [activeEntries]="activeEntries"
|
11589 | [animations]="animations"
|
11590 | (legendLabelClick)="onClick($event)"
|
11591 | (legendLabelActivate)="onActivate($event)"
|
11592 | (legendLabelDeactivate)="onDeactivate($event)"
|
11593 | >
|
11594 | <svg:g class="polar-chart chart" [attr.transform]="transform">
|
11595 | <svg:g [attr.transform]="transformPlot">
|
11596 | <svg:circle class="polar-chart-background" cx="0" cy="0" [attr.r]="this.outerRadius" />
|
11597 | <svg:g *ngIf="showGridLines">
|
11598 | <svg:circle
|
11599 | *ngFor="let r of radiusTicks"
|
11600 | class="gridline-path radial-gridline-path"
|
11601 | cx="0"
|
11602 | cy="0"
|
11603 | [attr.r]="r"
|
11604 | />
|
11605 | </svg:g>
|
11606 | <svg:g *ngIf="xAxis">
|
11607 | <svg:g
|
11608 | ngx-charts-pie-label
|
11609 | *ngFor="let tick of thetaTicks"
|
11610 | [data]="tick"
|
11611 | [radius]="outerRadius"
|
11612 | [label]="tick.label"
|
11613 | [max]="outerRadius"
|
11614 | [value]="showGridLines ? 1 : outerRadius"
|
11615 | [explodeSlices]="true"
|
11616 | [animations]="animations"
|
11617 | [labelTrim]="labelTrim"
|
11618 | [labelTrimSize]="labelTrimSize"
|
11619 | ></svg:g>
|
11620 | </svg:g>
|
11621 | </svg:g>
|
11622 | <svg:g
|
11623 | ngx-charts-y-axis
|
11624 | [attr.transform]="transformYAxis"
|
11625 | *ngIf="yAxis"
|
11626 | [yScale]="yAxisScale"
|
11627 | [dims]="yAxisDims"
|
11628 | [showGridLines]="showGridLines"
|
11629 | [showLabel]="showYAxisLabel"
|
11630 | [labelText]="yAxisLabel"
|
11631 | [trimTicks]="trimYAxisTicks"
|
11632 | [maxTickLength]="maxYAxisTickLength"
|
11633 | [tickFormatting]="yAxisTickFormatting"
|
11634 | (dimensionsChanged)="updateYAxisWidth($event)"
|
11635 | ></svg:g>
|
11636 | <svg:g
|
11637 | ngx-charts-axis-label
|
11638 | *ngIf="xAxis && showXAxisLabel"
|
11639 | [label]="xAxisLabel"
|
11640 | [offset]="labelOffset"
|
11641 | [orient]="orientation.Bottom"
|
11642 | [height]="dims.height"
|
11643 | [width]="dims.width"
|
11644 | ></svg:g>
|
11645 | <svg:g [attr.transform]="transformPlot">
|
11646 | <svg:g *ngFor="let series of results; trackBy: trackBy" [@animationState]="'active'">
|
11647 | <svg:g
|
11648 | ngx-charts-polar-series
|
11649 | [gradient]="gradient"
|
11650 | [xScale]="xScale"
|
11651 | [yScale]="yScale"
|
11652 | [colors]="colors"
|
11653 | [data]="series"
|
11654 | [activeEntries]="activeEntries"
|
11655 | [scaleType]="scaleType"
|
11656 | [curve]="curve"
|
11657 | [rangeFillOpacity]="rangeFillOpacity"
|
11658 | [animations]="animations"
|
11659 | [tooltipDisabled]="tooltipDisabled"
|
11660 | [tooltipTemplate]="tooltipTemplate"
|
11661 | (select)="onClick($event)"
|
11662 | (activate)="onActivate($event)"
|
11663 | (deactivate)="onDeactivate($event)"
|
11664 | />
|
11665 | </svg:g>
|
11666 | </svg:g>
|
11667 | </svg:g>
|
11668 | </ngx-charts-chart>
|
11669 | `,
|
11670 | encapsulation: ViewEncapsulation.None,
|
11671 | changeDetection: ChangeDetectionStrategy.OnPush,
|
11672 | animations: [
|
11673 | trigger('animationState', [
|
11674 | transition(':leave', [
|
11675 | style({
|
11676 | opacity: 1
|
11677 | }),
|
11678 | animate(500, style({
|
11679 | opacity: 0
|
11680 | }))
|
11681 | ])
|
11682 | ])
|
11683 | ],
|
11684 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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{-webkit-animation:.75s ease-in fadeIn;animation:.75s ease-in fadeIn}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.pie-label-line{stroke-dasharray:100%}.pie-label-line.animation{-webkit-animation:3s linear drawOut;animation:3s linear drawOut;transition:d .75s}@-webkit-keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}@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{pointer-events:none}.polar-series-path{pointer-events:none}\n"]
|
11685 | },] }
|
11686 | ];
|
11687 | PolarChartComponent.propDecorators = {
|
11688 | legend: [{ type: Input }],
|
11689 | legendTitle: [{ type: Input }],
|
11690 | legendPosition: [{ type: Input }],
|
11691 | xAxis: [{ type: Input }],
|
11692 | yAxis: [{ type: Input }],
|
11693 | showXAxisLabel: [{ type: Input }],
|
11694 | showYAxisLabel: [{ type: Input }],
|
11695 | xAxisLabel: [{ type: Input }],
|
11696 | yAxisLabel: [{ type: Input }],
|
11697 | autoScale: [{ type: Input }],
|
11698 | showGridLines: [{ type: Input }],
|
11699 | curve: [{ type: Input }],
|
11700 | activeEntries: [{ type: Input }],
|
11701 | schemeType: [{ type: Input }],
|
11702 | rangeFillOpacity: [{ type: Input }],
|
11703 | trimYAxisTicks: [{ type: Input }],
|
11704 | maxYAxisTickLength: [{ type: Input }],
|
11705 | xAxisTickFormatting: [{ type: Input }],
|
11706 | yAxisTickFormatting: [{ type: Input }],
|
11707 | roundDomains: [{ type: Input }],
|
11708 | tooltipDisabled: [{ type: Input }],
|
11709 | showSeriesOnHover: [{ type: Input }],
|
11710 | gradient: [{ type: Input }],
|
11711 | yAxisMinScale: [{ type: Input }],
|
11712 | labelTrim: [{ type: Input }],
|
11713 | labelTrimSize: [{ type: Input }],
|
11714 | activate: [{ type: Output }],
|
11715 | deactivate: [{ type: Output }],
|
11716 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
11717 | };
|
11718 |
|
11719 | class PolarSeriesComponent {
|
11720 | constructor() {
|
11721 | this.tooltipDisabled = false;
|
11722 | this.gradient = false;
|
11723 | this.animations = true;
|
11724 | this.select = new EventEmitter();
|
11725 | this.activate = new EventEmitter();
|
11726 | this.deactivate = new EventEmitter();
|
11727 | this.circleRadius = 3;
|
11728 | this.barOrientation = BarOrientation;
|
11729 | this.placementTypes = PlacementTypes;
|
11730 | this.styleTypes = StyleTypes;
|
11731 | }
|
11732 | ngOnChanges(changes) {
|
11733 | this.update();
|
11734 | }
|
11735 | update() {
|
11736 | this.updateGradients();
|
11737 | const line = this.getLineGenerator();
|
11738 | const data = this.sortData(this.data.series);
|
11739 | const seriesName = this.data.name;
|
11740 | const linearScaleType = this.colors.scaleType === ScaleType.Linear;
|
11741 | const min = this.yScale.domain()[0];
|
11742 | this.seriesColor = this.colors.getColor(linearScaleType ? min : seriesName);
|
11743 | this.path = line(data) || '';
|
11744 | this.circles = data.map(d => {
|
11745 | const a = this.getAngle(d);
|
11746 | const r = this.getRadius(d);
|
11747 | const value = d.value;
|
11748 | const color = this.colors.getColor(linearScaleType ? Math.abs(value) : seriesName);
|
11749 | const cData = Object.assign({}, d, {
|
11750 | series: seriesName,
|
11751 | value,
|
11752 | name: d.name
|
11753 | });
|
11754 | return {
|
11755 | data: cData,
|
11756 | cx: r * Math.sin(a),
|
11757 | cy: -r * Math.cos(a),
|
11758 | value,
|
11759 | color,
|
11760 | label: d.name
|
11761 | };
|
11762 | });
|
11763 | this.active = this.isActive(this.data);
|
11764 | this.inactive = this.isInactive(this.data);
|
11765 | this.tooltipText = this.tooltipText || (c => this.defaultTooltipText(c));
|
11766 | }
|
11767 | getAngle(d) {
|
11768 | const label = d.name;
|
11769 | if (this.scaleType === ScaleType.Time) {
|
11770 | return this.xScale(label);
|
11771 | }
|
11772 | else if (this.scaleType === ScaleType.Linear) {
|
11773 | return this.xScale(Number(label));
|
11774 | }
|
11775 | return this.xScale(label);
|
11776 | }
|
11777 | getRadius(d) {
|
11778 | return this.yScale(d.value);
|
11779 | }
|
11780 | getLineGenerator() {
|
11781 | return lineRadial()
|
11782 | .angle(d => this.getAngle(d))
|
11783 | .radius(d => this.getRadius(d))
|
11784 | .curve(this.curve);
|
11785 | }
|
11786 | sortData(data) {
|
11787 | if (this.scaleType === ScaleType.Linear) {
|
11788 | return sortLinear(data, 'name');
|
11789 | }
|
11790 | else if (this.scaleType === ScaleType.Time) {
|
11791 | return sortByTime(data, 'name');
|
11792 | }
|
11793 | return sortByDomain(data, 'name', 'asc', this.xScale.domain());
|
11794 | }
|
11795 | isActive(entry) {
|
11796 | if (!this.activeEntries)
|
11797 | return false;
|
11798 | const item = this.activeEntries.find(d => {
|
11799 | return entry.name === d.name;
|
11800 | });
|
11801 | return item !== undefined;
|
11802 | }
|
11803 | isInactive(entry) {
|
11804 | if (!this.activeEntries || this.activeEntries.length === 0)
|
11805 | return false;
|
11806 | const item = this.activeEntries.find(d => {
|
11807 | return entry.name === d.name;
|
11808 | });
|
11809 | return item === undefined;
|
11810 | }
|
11811 | defaultTooltipText({ label, value }) {
|
11812 | return `
|
11813 | <span class="tooltip-label">${escapeLabel(this.data.name)} • ${escapeLabel(label)}</span>
|
11814 | <span class="tooltip-val">${value.toLocaleString()}</span>
|
11815 | `;
|
11816 | }
|
11817 | updateGradients() {
|
11818 | this.hasGradient = this.gradient || this.colors.scaleType === ScaleType.Linear;
|
11819 | if (!this.hasGradient) {
|
11820 | return;
|
11821 | }
|
11822 | this.gradientId = 'grad' + id().toString();
|
11823 | this.gradientUrl = `url(#${this.gradientId})`;
|
11824 | if (this.colors.scaleType === ScaleType.Linear) {
|
11825 | const values = this.data.series.map(d => d.value);
|
11826 | const max = Math.max(...values);
|
11827 | const min = Math.min(...values);
|
11828 | this.gradientStops = this.colors.getLinearGradientStops(max, min);
|
11829 | }
|
11830 | else {
|
11831 | this.gradientStops = undefined;
|
11832 | }
|
11833 | }
|
11834 | }
|
11835 | PolarSeriesComponent.decorators = [
|
11836 | { type: Component, args: [{
|
11837 | selector: 'g[ngx-charts-polar-series]',
|
11838 | template: `
|
11839 | <svg:g class="polar-charts-series">
|
11840 | <defs>
|
11841 | <svg:g
|
11842 | ngx-charts-svg-radial-gradient
|
11843 | *ngIf="hasGradient"
|
11844 | [color]="seriesColor"
|
11845 | [name]="gradientId"
|
11846 | [startOpacity]="0.25"
|
11847 | [endOpacity]="1"
|
11848 | [stops]="gradientStops"
|
11849 | />
|
11850 | </defs>
|
11851 | <svg:g
|
11852 | ngx-charts-line
|
11853 | class="polar-series-path"
|
11854 | [path]="path"
|
11855 | [stroke]="hasGradient ? gradientUrl : seriesColor"
|
11856 | [class.active]="active"
|
11857 | [class.inactive]="inactive"
|
11858 | [attr.fill-opacity]="rangeFillOpacity"
|
11859 | [fill]="hasGradient ? gradientUrl : seriesColor"
|
11860 | [animations]="animations"
|
11861 | />
|
11862 | <svg:g
|
11863 | ngx-charts-circle
|
11864 | *ngFor="let circle of circles"
|
11865 | class="circle"
|
11866 | [cx]="circle.cx"
|
11867 | [cy]="circle.cy"
|
11868 | [r]="circleRadius"
|
11869 | [fill]="circle.color"
|
11870 | [style.opacity]="inactive ? 0.2 : 1"
|
11871 | ngx-tooltip
|
11872 | [tooltipDisabled]="tooltipDisabled"
|
11873 | [tooltipPlacement]="placementTypes.Top"
|
11874 | [tooltipType]="styleTypes.tooltip"
|
11875 | [tooltipTitle]="tooltipTemplate ? undefined : tooltipText(circle)"
|
11876 | [tooltipTemplate]="tooltipTemplate"
|
11877 | [tooltipContext]="circle.data"
|
11878 | (select)="select.emit(circle.data)"
|
11879 | (activate)="activate.emit({ name: circle.data.series })"
|
11880 | (deactivate)="deactivate.emit({ name: circle.data.series })"
|
11881 | ></svg:g>
|
11882 | </svg:g>
|
11883 | `,
|
11884 | changeDetection: ChangeDetectionStrategy.OnPush
|
11885 | },] }
|
11886 | ];
|
11887 | PolarSeriesComponent.propDecorators = {
|
11888 | name: [{ type: Input }],
|
11889 | data: [{ type: Input }],
|
11890 | xScale: [{ type: Input }],
|
11891 | yScale: [{ type: Input }],
|
11892 | colors: [{ type: Input }],
|
11893 | scaleType: [{ type: Input }],
|
11894 | curve: [{ type: Input }],
|
11895 | activeEntries: [{ type: Input }],
|
11896 | rangeFillOpacity: [{ type: Input }],
|
11897 | tooltipDisabled: [{ type: Input }],
|
11898 | tooltipText: [{ type: Input }],
|
11899 | gradient: [{ type: Input }],
|
11900 | tooltipTemplate: [{ type: Input }],
|
11901 | animations: [{ type: Input }],
|
11902 | select: [{ type: Output }],
|
11903 | activate: [{ type: Output }],
|
11904 | deactivate: [{ type: Output }]
|
11905 | };
|
11906 |
|
11907 | class AdvancedPieChartComponent extends BaseChartComponent {
|
11908 | constructor() {
|
11909 | super(...arguments);
|
11910 | this.activeEntries = [];
|
11911 | this.tooltipDisabled = false;
|
11912 | this.label = 'Total';
|
11913 | this.activate = new EventEmitter();
|
11914 | this.deactivate = new EventEmitter();
|
11915 | this.margin = [20, 20, 20, 20];
|
11916 | }
|
11917 | update() {
|
11918 | super.update();
|
11919 | this.dims = calculateViewDimensions({
|
11920 | width: (this.width * 4) / 12.0,
|
11921 | height: this.height,
|
11922 | margins: this.margin
|
11923 | });
|
11924 | this.formatDates();
|
11925 | this.domain = this.getDomain();
|
11926 | this.setColors();
|
11927 | const xOffset = this.dims.width / 2;
|
11928 | const yOffset = this.margin[0] + this.dims.height / 2;
|
11929 | this.legendWidth = this.width - this.dims.width - this.margin[1];
|
11930 | this.outerRadius = Math.min(this.dims.width, this.dims.height) / 2.5;
|
11931 | this.innerRadius = this.outerRadius * 0.75;
|
11932 | this.transform = `translate(${xOffset} , ${yOffset})`;
|
11933 | }
|
11934 | getDomain() {
|
11935 | return this.results.map(d => d.label);
|
11936 | }
|
11937 | onClick(data) {
|
11938 | this.select.emit(data);
|
11939 | }
|
11940 | setColors() {
|
11941 | this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
11942 | }
|
11943 | onActivate(item, fromLegend = false) {
|
11944 | item = this.results.find(d => {
|
11945 | if (fromLegend) {
|
11946 | return d.label === item.name;
|
11947 | }
|
11948 | else {
|
11949 | return d.name === item.name;
|
11950 | }
|
11951 | });
|
11952 | const idx = this.activeEntries.findIndex(d => {
|
11953 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
11954 | });
|
11955 | if (idx > -1) {
|
11956 | return;
|
11957 | }
|
11958 | this.activeEntries = [item, ...this.activeEntries];
|
11959 | this.activate.emit({ value: item, entries: this.activeEntries });
|
11960 | }
|
11961 | onDeactivate(item, fromLegend = false) {
|
11962 | item = this.results.find(d => {
|
11963 | if (fromLegend) {
|
11964 | return d.label === item.name;
|
11965 | }
|
11966 | else {
|
11967 | return d.name === item.name;
|
11968 | }
|
11969 | });
|
11970 | const idx = this.activeEntries.findIndex(d => {
|
11971 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
11972 | });
|
11973 | this.activeEntries.splice(idx, 1);
|
11974 | this.activeEntries = [...this.activeEntries];
|
11975 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
11976 | }
|
11977 | }
|
11978 | AdvancedPieChartComponent.decorators = [
|
11979 | { type: Component, args: [{
|
11980 | selector: 'ngx-charts-advanced-pie-chart',
|
11981 | template: `
|
11982 | <div [style.width.px]="width" [style.height.px]="height">
|
11983 | <div class="advanced-pie chart" [style.width.px]="dims.width" [style.height.px]="dims.height">
|
11984 | <ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
11985 | <svg:g [attr.transform]="transform" class="pie chart">
|
11986 | <svg:g
|
11987 | ngx-charts-pie-series
|
11988 | [colors]="colors"
|
11989 | [series]="results"
|
11990 | [innerRadius]="innerRadius"
|
11991 | [activeEntries]="activeEntries"
|
11992 | [outerRadius]="outerRadius"
|
11993 | [gradient]="gradient"
|
11994 | [tooltipDisabled]="tooltipDisabled"
|
11995 | [tooltipTemplate]="tooltipTemplate"
|
11996 | [tooltipText]="tooltipText"
|
11997 | (select)="onClick($event)"
|
11998 | (activate)="onActivate($event)"
|
11999 | (deactivate)="onDeactivate($event)"
|
12000 | [animations]="animations"
|
12001 | ></svg:g>
|
12002 | </svg:g>
|
12003 | </ngx-charts-chart>
|
12004 | </div>
|
12005 | <div class="advanced-pie-legend-wrapper" [style.width.px]="width - dims.width" [style.height.px]="height">
|
12006 | <ngx-charts-advanced-legend
|
12007 | [data]="results"
|
12008 | [colors]="colors"
|
12009 | [width]="width - dims.width - margin[1]"
|
12010 | [label]="label"
|
12011 | [animations]="animations"
|
12012 | [valueFormatting]="valueFormatting"
|
12013 | [labelFormatting]="nameFormatting"
|
12014 | [percentageFormatting]="percentageFormatting"
|
12015 | (select)="onClick($event)"
|
12016 | (activate)="onActivate($event, true)"
|
12017 | (deactivate)="onDeactivate($event, true)"
|
12018 | >
|
12019 | </ngx-charts-advanced-legend>
|
12020 | </div>
|
12021 | </div>
|
12022 | `,
|
12023 | encapsulation: ViewEncapsulation.None,
|
12024 | changeDetection: ChangeDetectionStrategy.OnPush,
|
12025 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
12026 | },] }
|
12027 | ];
|
12028 | AdvancedPieChartComponent.propDecorators = {
|
12029 | gradient: [{ type: Input }],
|
12030 | activeEntries: [{ type: Input }],
|
12031 | tooltipDisabled: [{ type: Input }],
|
12032 | tooltipText: [{ type: Input }],
|
12033 | label: [{ type: Input }],
|
12034 | activate: [{ type: Output }],
|
12035 | deactivate: [{ type: Output }],
|
12036 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
12037 | valueFormatting: [{ type: Input }],
|
12038 | nameFormatting: [{ type: Input }],
|
12039 | percentageFormatting: [{ type: Input }]
|
12040 | };
|
12041 |
|
12042 | class PieLabelComponent {
|
12043 | constructor(platformId) {
|
12044 | this.platformId = platformId;
|
12045 | this.animations = true;
|
12046 | this.labelTrim = true;
|
12047 | this.labelTrimSize = 10;
|
12048 | this.trimLabel = trimLabel;
|
12049 | }
|
12050 | ngOnChanges(changes) {
|
12051 | this.setTransforms();
|
12052 | this.update();
|
12053 | }
|
12054 | setTransforms() {
|
12055 | if (isPlatformServer(this.platformId)) {
|
12056 | this.styleTransform = `translate3d(${this.textX}px,${this.textY}px, 0)`;
|
12057 | this.attrTransform = `translate(${this.textX},${this.textY})`;
|
12058 | this.textTransition = !this.animations ? null : 'transform 0.75s';
|
12059 | }
|
12060 | else {
|
12061 | const isIE = /(edge|msie|trident)/i.test(navigator.userAgent);
|
12062 | this.styleTransform = isIE ? null : `translate3d(${this.textX}px,${this.textY}px, 0)`;
|
12063 | this.attrTransform = !isIE ? null : `translate(${this.textX},${this.textY})`;
|
12064 | this.textTransition = isIE || !this.animations ? null : 'transform 0.75s';
|
12065 | }
|
12066 | }
|
12067 | update() {
|
12068 | let startRadius = this.radius;
|
12069 | if (this.explodeSlices) {
|
12070 | startRadius = (this.radius * this.value) / this.max;
|
12071 | }
|
12072 | const innerArc = arc().innerRadius(startRadius).outerRadius(startRadius);
|
12073 |
|
12074 | const innerPos = innerArc.centroid(this.data);
|
12075 | let scale = this.data.pos[1] / innerPos[1];
|
12076 | if (this.data.pos[1] === 0 || innerPos[1] === 0) {
|
12077 | scale = 1;
|
12078 | }
|
12079 | const outerPos = [scale * innerPos[0], scale * innerPos[1]];
|
12080 | this.line = `M${innerPos}L${outerPos}L${this.data.pos}`;
|
12081 | }
|
12082 | get textX() {
|
12083 | return this.data.pos[0];
|
12084 | }
|
12085 | get textY() {
|
12086 | return this.data.pos[1];
|
12087 | }
|
12088 | textAnchor() {
|
12089 | return this.midAngle(this.data) < Math.PI ? TextAnchor.Start : TextAnchor.End;
|
12090 | }
|
12091 | midAngle(d) {
|
12092 | return d.startAngle + (d.endAngle - d.startAngle) / 2;
|
12093 | }
|
12094 | }
|
12095 | PieLabelComponent.decorators = [
|
12096 | { type: Component, args: [{
|
12097 | selector: 'g[ngx-charts-pie-label]',
|
12098 | template: `
|
12099 | <title>{{ label }}</title>
|
12100 | <svg:g [attr.transform]="attrTransform" [style.transform]="styleTransform" [style.transition]="textTransition">
|
12101 | <svg:text
|
12102 | class="pie-label"
|
12103 | [class.animation]="animations"
|
12104 | dy=".35em"
|
12105 | [style.textAnchor]="textAnchor()"
|
12106 | [style.shapeRendering]="'crispEdges'"
|
12107 | >
|
12108 | {{ labelTrim ? trimLabel(label, labelTrimSize) : label }}
|
12109 | </svg:text>
|
12110 | </svg:g>
|
12111 | <svg:path
|
12112 | [attr.d]="line"
|
12113 | [attr.stroke]="color"
|
12114 | fill="none"
|
12115 | class="pie-label-line line"
|
12116 | [class.animation]="animations"
|
12117 | ></svg:path>
|
12118 | `,
|
12119 | changeDetection: ChangeDetectionStrategy.OnPush
|
12120 | },] }
|
12121 | ];
|
12122 | PieLabelComponent.ctorParameters = () => [
|
12123 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
12124 | ];
|
12125 | PieLabelComponent.propDecorators = {
|
12126 | data: [{ type: Input }],
|
12127 | radius: [{ type: Input }],
|
12128 | label: [{ type: Input }],
|
12129 | color: [{ type: Input }],
|
12130 | max: [{ type: Input }],
|
12131 | value: [{ type: Input }],
|
12132 | explodeSlices: [{ type: Input }],
|
12133 | animations: [{ type: Input }],
|
12134 | labelTrim: [{ type: Input }],
|
12135 | labelTrimSize: [{ type: Input }]
|
12136 | };
|
12137 |
|
12138 | class PieArcComponent {
|
12139 | constructor(element) {
|
12140 | this.startAngle = 0;
|
12141 | this.endAngle = Math.PI * 2;
|
12142 | this.cornerRadius = 0;
|
12143 | this.explodeSlices = false;
|
12144 | this.gradient = false;
|
12145 | this.animate = true;
|
12146 | this.pointerEvents = true;
|
12147 | this.isActive = false;
|
12148 | this.select = new EventEmitter();
|
12149 | this.activate = new EventEmitter();
|
12150 | this.deactivate = new EventEmitter();
|
12151 | this.dblclick = new EventEmitter();
|
12152 | this.barOrientation = BarOrientation;
|
12153 | this.initialized = false;
|
12154 | this.element = element.nativeElement;
|
12155 | }
|
12156 | ngOnChanges(changes) {
|
12157 | this.update();
|
12158 | }
|
12159 | getGradient() {
|
12160 | return this.gradient ? this.gradientFill : this.fill;
|
12161 | }
|
12162 | getPointerEvents() {
|
12163 | return this.pointerEvents ? 'auto' : 'none';
|
12164 | }
|
12165 | update() {
|
12166 | const calc = this.calculateArc();
|
12167 | this.startOpacity = 0.5;
|
12168 | this.radialGradientId = 'linearGrad' + id().toString();
|
12169 | this.gradientFill = `url(#${this.radialGradientId})`;
|
12170 | if (this.animate) {
|
12171 | if (this.initialized) {
|
12172 | this.updateAnimation();
|
12173 | }
|
12174 | else {
|
12175 | this.loadAnimation();
|
12176 | this.initialized = true;
|
12177 | }
|
12178 | }
|
12179 | else {
|
12180 | this.path = calc.startAngle(this.startAngle).endAngle(this.endAngle)();
|
12181 | }
|
12182 | }
|
12183 | calculateArc() {
|
12184 | let outerRadius = this.outerRadius;
|
12185 | if (this.explodeSlices && this.innerRadius === 0) {
|
12186 | outerRadius = (this.outerRadius * this.value) / this.max;
|
12187 | }
|
12188 | return arc().innerRadius(this.innerRadius).outerRadius(outerRadius).cornerRadius(this.cornerRadius);
|
12189 | }
|
12190 | loadAnimation() {
|
12191 | const node = select(this.element)
|
12192 | .selectAll('.arc')
|
12193 | .data([{ startAngle: this.startAngle, endAngle: this.endAngle }]);
|
12194 | const calc = this.calculateArc();
|
12195 | node
|
12196 | .transition()
|
12197 | .attrTween('d', function (d) {
|
12198 | this._current = this._current || d;
|
12199 | const copyOfD = Object.assign({}, d);
|
12200 | copyOfD.endAngle = copyOfD.startAngle;
|
12201 | const interpolater = interpolate(copyOfD, copyOfD);
|
12202 | this._current = interpolater(0);
|
12203 | return function (t) {
|
12204 | return calc(interpolater(t));
|
12205 | };
|
12206 | })
|
12207 | .transition()
|
12208 | .duration(750)
|
12209 | .attrTween('d', function (d) {
|
12210 | this._current = this._current || d;
|
12211 | const interpolater = interpolate(this._current, d);
|
12212 | this._current = interpolater(0);
|
12213 | return function (t) {
|
12214 | return calc(interpolater(t));
|
12215 | };
|
12216 | });
|
12217 | }
|
12218 | updateAnimation() {
|
12219 | const node = select(this.element)
|
12220 | .selectAll('.arc')
|
12221 | .data([{ startAngle: this.startAngle, endAngle: this.endAngle }]);
|
12222 | const calc = this.calculateArc();
|
12223 | node
|
12224 | .transition()
|
12225 | .duration(750)
|
12226 | .attrTween('d', function (d) {
|
12227 | this._current = this._current || d;
|
12228 | const interpolater = interpolate(this._current, d);
|
12229 | this._current = interpolater(0);
|
12230 | return function (t) {
|
12231 | return calc(interpolater(t));
|
12232 | };
|
12233 | });
|
12234 | }
|
12235 | onClick() {
|
12236 | clearTimeout(this._timeout);
|
12237 | this._timeout = setTimeout(() => this.select.emit(this.data), 200);
|
12238 | }
|
12239 | onDblClick(event) {
|
12240 | event.preventDefault();
|
12241 | event.stopPropagation();
|
12242 | clearTimeout(this._timeout);
|
12243 | this.dblclick.emit({
|
12244 | data: this.data,
|
12245 | nativeEvent: event
|
12246 | });
|
12247 | }
|
12248 | }
|
12249 | PieArcComponent.decorators = [
|
12250 | { type: Component, args: [{
|
12251 | selector: 'g[ngx-charts-pie-arc]',
|
12252 | template: `
|
12253 | <svg:g class="arc-group">
|
12254 | <svg:defs *ngIf="gradient">
|
12255 | <svg:g ngx-charts-svg-radial-gradient [color]="fill" [name]="radialGradientId" [startOpacity]="startOpacity" />
|
12256 | </svg:defs>
|
12257 | <svg:path
|
12258 | [attr.d]="path"
|
12259 | class="arc"
|
12260 | [class.active]="isActive"
|
12261 | [attr.fill]="getGradient()"
|
12262 | (click)="onClick()"
|
12263 | (dblclick)="onDblClick($event)"
|
12264 | (mouseenter)="activate.emit(data)"
|
12265 | (mouseleave)="deactivate.emit(data)"
|
12266 | [style.pointer-events]="getPointerEvents()"
|
12267 | />
|
12268 | </svg:g>
|
12269 | `,
|
12270 | changeDetection: ChangeDetectionStrategy.OnPush
|
12271 | },] }
|
12272 | ];
|
12273 | PieArcComponent.ctorParameters = () => [
|
12274 | { type: ElementRef }
|
12275 | ];
|
12276 | PieArcComponent.propDecorators = {
|
12277 | fill: [{ type: Input }],
|
12278 | startAngle: [{ type: Input }],
|
12279 | endAngle: [{ type: Input }],
|
12280 | innerRadius: [{ type: Input }],
|
12281 | outerRadius: [{ type: Input }],
|
12282 | cornerRadius: [{ type: Input }],
|
12283 | value: [{ type: Input }],
|
12284 | max: [{ type: Input }],
|
12285 | data: [{ type: Input }],
|
12286 | explodeSlices: [{ type: Input }],
|
12287 | gradient: [{ type: Input }],
|
12288 | animate: [{ type: Input }],
|
12289 | pointerEvents: [{ type: Input }],
|
12290 | isActive: [{ type: Input }],
|
12291 | select: [{ type: Output }],
|
12292 | activate: [{ type: Output }],
|
12293 | deactivate: [{ type: Output }],
|
12294 | dblclick: [{ type: Output }]
|
12295 | };
|
12296 |
|
12297 | class PieChartComponent extends BaseChartComponent {
|
12298 | constructor() {
|
12299 | super(...arguments);
|
12300 | this.labels = false;
|
12301 | this.legend = false;
|
12302 | this.legendTitle = 'Legend';
|
12303 | this.legendPosition = LegendPosition.Right;
|
12304 | this.explodeSlices = false;
|
12305 | this.doughnut = false;
|
12306 | this.arcWidth = 0.25;
|
12307 | this.activeEntries = [];
|
12308 | this.tooltipDisabled = false;
|
12309 | this.trimLabels = true;
|
12310 | this.maxLabelLength = 10;
|
12311 | this.dblclick = new EventEmitter();
|
12312 | this.select = new EventEmitter();
|
12313 | this.activate = new EventEmitter();
|
12314 | this.deactivate = new EventEmitter();
|
12315 | }
|
12316 | update() {
|
12317 | super.update();
|
12318 | if (this.labels && this.hasNoOptionalMarginsSet()) {
|
12319 | this.margins = [30, 80, 30, 80];
|
12320 | }
|
12321 | else if (!this.labels && this.hasNoOptionalMarginsSet()) {
|
12322 |
|
12323 | this.margins = [20, 20, 20, 20];
|
12324 | }
|
12325 | this.dims = calculateViewDimensions({
|
12326 | width: this.width,
|
12327 | height: this.height,
|
12328 | margins: this.margins,
|
12329 | showLegend: this.legend,
|
12330 | legendPosition: this.legendPosition
|
12331 | });
|
12332 | this.formatDates();
|
12333 | const xOffset = this.margins[3] + this.dims.width / 2;
|
12334 | const yOffset = this.margins[0] + this.dims.height / 2;
|
12335 | this.translation = `translate(${xOffset}, ${yOffset})`;
|
12336 | this.outerRadius = Math.min(this.dims.width, this.dims.height);
|
12337 | if (this.labels) {
|
12338 |
|
12339 | this.outerRadius /= 3;
|
12340 | }
|
12341 | else {
|
12342 | this.outerRadius /= 2;
|
12343 | }
|
12344 | this.innerRadius = 0;
|
12345 | if (this.doughnut) {
|
12346 | this.innerRadius = this.outerRadius * (1 - this.arcWidth);
|
12347 | }
|
12348 | this.domain = this.getDomain();
|
12349 |
|
12350 | this.data = this.results.sort((a, b) => {
|
12351 | return this.domain.indexOf(a.name) - this.domain.indexOf(b.name);
|
12352 | });
|
12353 | this.setColors();
|
12354 | this.legendOptions = this.getLegendOptions();
|
12355 | }
|
12356 | getDomain() {
|
12357 | return this.results.map(d => d.label);
|
12358 | }
|
12359 | onClick(data) {
|
12360 | this.select.emit(data);
|
12361 | }
|
12362 | setColors() {
|
12363 | this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
12364 | }
|
12365 | getLegendOptions() {
|
12366 | return {
|
12367 | scaleType: ScaleType.Ordinal,
|
12368 | domain: this.domain,
|
12369 | colors: this.colors,
|
12370 | title: this.legendTitle,
|
12371 | position: this.legendPosition
|
12372 | };
|
12373 | }
|
12374 | onActivate(item, fromLegend = false) {
|
12375 | item = this.results.find(d => {
|
12376 | if (fromLegend) {
|
12377 | return d.label === item.name;
|
12378 | }
|
12379 | else {
|
12380 | return d.name === item.name;
|
12381 | }
|
12382 | });
|
12383 | const idx = this.activeEntries.findIndex(d => {
|
12384 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
12385 | });
|
12386 | if (idx > -1) {
|
12387 | return;
|
12388 | }
|
12389 | this.activeEntries = [item, ...this.activeEntries];
|
12390 | this.activate.emit({ value: item, entries: this.activeEntries });
|
12391 | }
|
12392 | onDeactivate(item, fromLegend = false) {
|
12393 | item = this.results.find(d => {
|
12394 | if (fromLegend) {
|
12395 | return d.label === item.name;
|
12396 | }
|
12397 | else {
|
12398 | return d.name === item.name;
|
12399 | }
|
12400 | });
|
12401 | const idx = this.activeEntries.findIndex(d => {
|
12402 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
12403 | });
|
12404 | this.activeEntries.splice(idx, 1);
|
12405 | this.activeEntries = [...this.activeEntries];
|
12406 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
12407 | }
|
12408 | hasNoOptionalMarginsSet() {
|
12409 | return !this.margins || this.margins.length <= 0;
|
12410 | }
|
12411 | }
|
12412 | PieChartComponent.decorators = [
|
12413 | { type: Component, args: [{
|
12414 | selector: 'ngx-charts-pie-chart',
|
12415 | template: `
|
12416 | <ngx-charts-chart
|
12417 | [view]="[width, height]"
|
12418 | [showLegend]="legend"
|
12419 | [legendOptions]="legendOptions"
|
12420 | [activeEntries]="activeEntries"
|
12421 | [animations]="animations"
|
12422 | (legendLabelActivate)="onActivate($event, true)"
|
12423 | (legendLabelDeactivate)="onDeactivate($event, true)"
|
12424 | (legendLabelClick)="onClick($event)"
|
12425 | >
|
12426 | <svg:g [attr.transform]="translation" class="pie-chart chart">
|
12427 | <svg:g
|
12428 | ngx-charts-pie-series
|
12429 | [colors]="colors"
|
12430 | [series]="data"
|
12431 | [showLabels]="labels"
|
12432 | [labelFormatting]="labelFormatting"
|
12433 | [trimLabels]="trimLabels"
|
12434 | [maxLabelLength]="maxLabelLength"
|
12435 | [activeEntries]="activeEntries"
|
12436 | [innerRadius]="innerRadius"
|
12437 | [outerRadius]="outerRadius"
|
12438 | [explodeSlices]="explodeSlices"
|
12439 | [gradient]="gradient"
|
12440 | [animations]="animations"
|
12441 | [tooltipDisabled]="tooltipDisabled"
|
12442 | [tooltipTemplate]="tooltipTemplate"
|
12443 | [tooltipText]="tooltipText"
|
12444 | (dblclick)="dblclick.emit($event)"
|
12445 | (select)="onClick($event)"
|
12446 | (activate)="onActivate($event)"
|
12447 | (deactivate)="onDeactivate($event)"
|
12448 | />
|
12449 | </svg:g>
|
12450 | </ngx-charts-chart>
|
12451 | `,
|
12452 | encapsulation: ViewEncapsulation.None,
|
12453 | changeDetection: ChangeDetectionStrategy.OnPush,
|
12454 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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{-webkit-animation:.75s ease-in fadeIn;animation:.75s ease-in fadeIn}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.pie-label-line{stroke-dasharray:100%}.pie-label-line.animation{-webkit-animation:3s linear drawOut;animation:3s linear drawOut;transition:d .75s}@-webkit-keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}@keyframes drawOut{0%{stroke-dashoffset:100%}to{stroke-dashoffset:0}}\n"]
|
12455 | },] }
|
12456 | ];
|
12457 | PieChartComponent.propDecorators = {
|
12458 | labels: [{ type: Input }],
|
12459 | legend: [{ type: Input }],
|
12460 | legendTitle: [{ type: Input }],
|
12461 | legendPosition: [{ type: Input }],
|
12462 | explodeSlices: [{ type: Input }],
|
12463 | doughnut: [{ type: Input }],
|
12464 | arcWidth: [{ type: Input }],
|
12465 | gradient: [{ type: Input }],
|
12466 | activeEntries: [{ type: Input }],
|
12467 | tooltipDisabled: [{ type: Input }],
|
12468 | labelFormatting: [{ type: Input }],
|
12469 | trimLabels: [{ type: Input }],
|
12470 | maxLabelLength: [{ type: Input }],
|
12471 | tooltipText: [{ type: Input }],
|
12472 | dblclick: [{ type: Output }],
|
12473 | margins: [{ type: Input }],
|
12474 | select: [{ type: Output }],
|
12475 | activate: [{ type: Output }],
|
12476 | deactivate: [{ type: Output }],
|
12477 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
12478 | };
|
12479 |
|
12480 | function gridSize(dims, len, minWidth) {
|
12481 | let rows = 1;
|
12482 | let cols = len;
|
12483 | const width = dims.width;
|
12484 | if (width > minWidth) {
|
12485 | while (width / cols < minWidth) {
|
12486 | rows += 1;
|
12487 | cols = Math.ceil(len / rows);
|
12488 | }
|
12489 | }
|
12490 | return [cols, rows];
|
12491 | }
|
12492 | function gridLayout(dims, data, minWidth, designatedTotal) {
|
12493 | const xScale = scaleBand();
|
12494 | const yScale = scaleBand();
|
12495 | const width = dims.width;
|
12496 | const height = dims.height;
|
12497 | const [columns, rows] = gridSize(dims, data.length, minWidth);
|
12498 | const xDomain = [];
|
12499 | const yDomain = [];
|
12500 | for (let i = 0; i < rows; i++) {
|
12501 | yDomain.push(i);
|
12502 | }
|
12503 | for (let i = 0; i < columns; i++) {
|
12504 | xDomain.push(i);
|
12505 | }
|
12506 | xScale.domain(xDomain);
|
12507 | yScale.domain(yDomain);
|
12508 | xScale.rangeRound([0, width], 0.1);
|
12509 | yScale.rangeRound([0, height], 0.1);
|
12510 | const res = [];
|
12511 | const total = designatedTotal ? designatedTotal : getTotal(data);
|
12512 | const cardWidth = xScale.bandwidth();
|
12513 | const cardHeight = yScale.bandwidth();
|
12514 | for (let i = 0; i < data.length; i++) {
|
12515 | res[i] = {};
|
12516 | res[i].data = {
|
12517 | name: data[i] ? data[i].name : '',
|
12518 | value: data[i] ? data[i].value : undefined,
|
12519 | extra: data[i] ? data[i].extra : undefined,
|
12520 | label: data[i] ? data[i].label : ''
|
12521 | };
|
12522 | res[i].x = xScale(i % columns);
|
12523 | res[i].y = yScale(Math.floor(i / columns));
|
12524 | res[i].width = cardWidth;
|
12525 | res[i].height = cardHeight;
|
12526 | res[i].data.percent = total > 0 ? res[i].data.value / total : 0;
|
12527 | res[i].data.total = total;
|
12528 | }
|
12529 | return res;
|
12530 | }
|
12531 | function getTotal(results) {
|
12532 | return results.map(d => (d ? d.value : 0)).reduce((sum, val) => sum + val, 0);
|
12533 | }
|
12534 |
|
12535 | class PieGridComponent extends BaseChartComponent {
|
12536 | constructor() {
|
12537 | super(...arguments);
|
12538 | this.tooltipDisabled = false;
|
12539 | this.label = 'Total';
|
12540 | this.minWidth = 150;
|
12541 | this.activeEntries = [];
|
12542 | this.activate = new EventEmitter();
|
12543 | this.deactivate = new EventEmitter();
|
12544 | this.margin = [20, 20, 20, 20];
|
12545 | this.placementTypes = PlacementTypes;
|
12546 | this.styleTypes = StyleTypes;
|
12547 | }
|
12548 | update() {
|
12549 | super.update();
|
12550 | this.dims = calculateViewDimensions({
|
12551 | width: this.width,
|
12552 | height: this.height,
|
12553 | margins: this.margin
|
12554 | });
|
12555 | this.formatDates();
|
12556 | this.domain = this.getDomain();
|
12557 | this.data = gridLayout(this.dims, this.results, this.minWidth, this.designatedTotal);
|
12558 | this.transform = `translate(${this.margin[3]} , ${this.margin[0]})`;
|
12559 | this.series = this.getSeries();
|
12560 | this.setColors();
|
12561 | this.tooltipText = this.tooltipText || this.defaultTooltipText;
|
12562 | }
|
12563 | defaultTooltipText({ data }) {
|
12564 | const label = trimLabel(formatLabel(data.name));
|
12565 | const val = data.value.toLocaleString();
|
12566 | return `
|
12567 | <span class="tooltip-label">${label}</span>
|
12568 | <span class="tooltip-val">${val}</span>
|
12569 | `;
|
12570 | }
|
12571 | getDomain() {
|
12572 | return this.results.map(d => d.label);
|
12573 | }
|
12574 | getSeries() {
|
12575 | const total = this.designatedTotal ? this.designatedTotal : this.getTotal();
|
12576 | return this.data.map(d => {
|
12577 | const baselineLabelHeight = 20;
|
12578 | const padding = 10;
|
12579 | const name = d.data.name;
|
12580 | const label = formatLabel(name);
|
12581 | const value = d.data.value;
|
12582 | const radius = min([d.width - padding, d.height - baselineLabelHeight]) / 2 - 5;
|
12583 | const innerRadius = radius * 0.9;
|
12584 | let count = 0;
|
12585 | const colors = () => {
|
12586 | count += 1;
|
12587 | if (count === 1) {
|
12588 | return 'rgba(100,100,100,0.3)';
|
12589 | }
|
12590 | else {
|
12591 | return this.colorScale.getColor(label);
|
12592 | }
|
12593 | };
|
12594 | const xPos = d.x + (d.width - padding) / 2;
|
12595 | const yPos = d.y + (d.height - baselineLabelHeight) / 2;
|
12596 | return {
|
12597 | transform: `translate(${xPos}, ${yPos})`,
|
12598 | colors,
|
12599 | innerRadius,
|
12600 | outerRadius: radius,
|
12601 | name,
|
12602 | label: trimLabel(label),
|
12603 | total: value,
|
12604 | value,
|
12605 | percent: format('.1%')(d.data.percent),
|
12606 | data: [
|
12607 | d,
|
12608 | {
|
12609 | data: {
|
12610 | other: true,
|
12611 | value: total - value,
|
12612 | name: d.data.name
|
12613 | }
|
12614 | }
|
12615 | ]
|
12616 | };
|
12617 | });
|
12618 | }
|
12619 | getTotal() {
|
12620 | return this.results.map(d => d.value).reduce((sum, d) => sum + d, 0);
|
12621 | }
|
12622 | onClick(data) {
|
12623 | this.select.emit(data);
|
12624 | }
|
12625 | setColors() {
|
12626 | this.colorScale = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
12627 | }
|
12628 | onActivate(item, fromLegend = false) {
|
12629 | item = this.results.find(d => {
|
12630 | if (fromLegend) {
|
12631 | return d.label === item.name;
|
12632 | }
|
12633 | else {
|
12634 | return d.name === item.name;
|
12635 | }
|
12636 | });
|
12637 | const idx = this.activeEntries.findIndex(d => {
|
12638 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
12639 | });
|
12640 | if (idx > -1) {
|
12641 | return;
|
12642 | }
|
12643 | this.activeEntries = [item, ...this.activeEntries];
|
12644 | this.activate.emit({ value: item, entries: this.activeEntries });
|
12645 | }
|
12646 | onDeactivate(item, fromLegend = false) {
|
12647 | item = this.results.find(d => {
|
12648 | if (fromLegend) {
|
12649 | return d.label === item.name;
|
12650 | }
|
12651 | else {
|
12652 | return d.name === item.name;
|
12653 | }
|
12654 | });
|
12655 | const idx = this.activeEntries.findIndex(d => {
|
12656 | return d.name === item.name && d.value === item.value && d.series === item.series;
|
12657 | });
|
12658 | this.activeEntries.splice(idx, 1);
|
12659 | this.activeEntries = [...this.activeEntries];
|
12660 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
12661 | }
|
12662 | }
|
12663 | PieGridComponent.decorators = [
|
12664 | { type: Component, args: [{
|
12665 | selector: 'ngx-charts-pie-grid',
|
12666 | template: `
|
12667 | <ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
12668 | <svg:g [attr.transform]="transform" class="pie-grid chart">
|
12669 | <svg:g *ngFor="let series of series" class="pie-grid-item" [attr.transform]="series.transform">
|
12670 | <svg:g
|
12671 | ngx-charts-pie-grid-series
|
12672 | [colors]="series.colors"
|
12673 | [data]="series.data"
|
12674 | [innerRadius]="series.innerRadius"
|
12675 | [outerRadius]="series.outerRadius"
|
12676 | [animations]="animations"
|
12677 | (select)="onClick($event)"
|
12678 | ngx-tooltip
|
12679 | [tooltipDisabled]="tooltipDisabled"
|
12680 | [tooltipPlacement]="placementTypes.Top"
|
12681 | [tooltipType]="styleTypes.tooltip"
|
12682 | [tooltipTitle]="tooltipTemplate ? undefined : tooltipText({ data: series })"
|
12683 | [tooltipTemplate]="tooltipTemplate"
|
12684 | [tooltipContext]="series.data[0].data"
|
12685 | (activate)="onActivate($event)"
|
12686 | (deactivate)="onDeactivate($event)"
|
12687 | />
|
12688 | <svg:text
|
12689 | *ngIf="animations"
|
12690 | class="label percent-label"
|
12691 | dy="-0.5em"
|
12692 | x="0"
|
12693 | y="5"
|
12694 | ngx-charts-count-up
|
12695 | [countTo]="series.percent"
|
12696 | [countSuffix]="'%'"
|
12697 | text-anchor="middle"
|
12698 | ></svg:text>
|
12699 | <svg:text *ngIf="!animations" class="label percent-label" dy="-0.5em" x="0" y="5" text-anchor="middle">
|
12700 | {{ series.percent.toLocaleString() }}
|
12701 | </svg:text>
|
12702 | <svg:text class="label" dy="0.5em" x="0" y="5" text-anchor="middle">
|
12703 | {{ series.label }}
|
12704 | </svg:text>
|
12705 | <svg:text
|
12706 | *ngIf="animations"
|
12707 | class="label"
|
12708 | dy="1.23em"
|
12709 | x="0"
|
12710 | [attr.y]="series.outerRadius"
|
12711 | text-anchor="middle"
|
12712 | ngx-charts-count-up
|
12713 | [countTo]="series.total"
|
12714 | [countPrefix]="label + ': '"
|
12715 | ></svg:text>
|
12716 | <svg:text
|
12717 | *ngIf="!animations"
|
12718 | class="label"
|
12719 | dy="1.23em"
|
12720 | x="0"
|
12721 | [attr.y]="series.outerRadius"
|
12722 | text-anchor="middle"
|
12723 | >
|
12724 | {{ label }}: {{ series.total.toLocaleString() }}
|
12725 | </svg:text>
|
12726 | </svg:g>
|
12727 | </svg:g>
|
12728 | </ngx-charts-chart>
|
12729 | `,
|
12730 | encapsulation: ViewEncapsulation.None,
|
12731 | changeDetection: ChangeDetectionStrategy.OnPush,
|
12732 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
12733 | },] }
|
12734 | ];
|
12735 | PieGridComponent.propDecorators = {
|
12736 | designatedTotal: [{ type: Input }],
|
12737 | tooltipDisabled: [{ type: Input }],
|
12738 | tooltipText: [{ type: Input }],
|
12739 | label: [{ type: Input }],
|
12740 | minWidth: [{ type: Input }],
|
12741 | activeEntries: [{ type: Input }],
|
12742 | activate: [{ type: Output }],
|
12743 | deactivate: [{ type: Output }],
|
12744 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
12745 | };
|
12746 |
|
12747 | class PieGridSeriesComponent {
|
12748 | constructor(element) {
|
12749 | this.innerRadius = 70;
|
12750 | this.outerRadius = 80;
|
12751 | this.animations = true;
|
12752 | this.select = new EventEmitter();
|
12753 | this.activate = new EventEmitter();
|
12754 | this.deactivate = new EventEmitter();
|
12755 | this.element = element.nativeElement;
|
12756 | }
|
12757 | ngOnChanges(changes) {
|
12758 | this.update();
|
12759 | }
|
12760 | update() {
|
12761 | this.layout = pie()
|
12762 | .value(d => d.data.value)
|
12763 | .sort(null);
|
12764 | this.arcs = this.getArcs();
|
12765 | }
|
12766 | getArcs() {
|
12767 | return this.layout(this.data).map((arc, index) => {
|
12768 | const label = arc.data.data.name;
|
12769 | const other = arc.data.data.other;
|
12770 | if (index === 0) {
|
12771 | arc.startAngle = 0;
|
12772 | }
|
12773 | const color = this.colors(label);
|
12774 | return {
|
12775 | data: arc.data.data,
|
12776 | class: 'arc ' + 'arc' + index,
|
12777 | fill: color,
|
12778 | startAngle: other ? 0 : arc.startAngle,
|
12779 | endAngle: arc.endAngle,
|
12780 | animate: this.animations && !other,
|
12781 | pointerEvents: !other
|
12782 | };
|
12783 | });
|
12784 | }
|
12785 | onClick(data) {
|
12786 | this.select.emit(this.data[0].data);
|
12787 | }
|
12788 | trackBy(index, item) {
|
12789 | return item.data.name;
|
12790 | }
|
12791 | label(arc) {
|
12792 | return arc.data.name;
|
12793 | }
|
12794 | color(arc) {
|
12795 | return this.colors(this.label(arc));
|
12796 | }
|
12797 | }
|
12798 | PieGridSeriesComponent.decorators = [
|
12799 | { type: Component, args: [{
|
12800 | selector: 'g[ngx-charts-pie-grid-series]',
|
12801 | template: `
|
12802 | <svg:g class="pie-grid-arcs">
|
12803 | <svg:g
|
12804 | ngx-charts-pie-arc
|
12805 | *ngFor="let arc of arcs; trackBy: trackBy"
|
12806 | [attr.class]="arc.class"
|
12807 | [startAngle]="arc.startAngle"
|
12808 | [endAngle]="arc.endAngle"
|
12809 | [innerRadius]="innerRadius"
|
12810 | [outerRadius]="outerRadius"
|
12811 | [fill]="color(arc)"
|
12812 | [value]="arc.data.value"
|
12813 | [data]="arc.data"
|
12814 | [gradient]="false"
|
12815 | [pointerEvents]="arc.pointerEvents"
|
12816 | [animate]="arc.animate"
|
12817 | (select)="onClick($event)"
|
12818 | (activate)="activate.emit($event)"
|
12819 | (deactivate)="deactivate.emit($event)"
|
12820 | ></svg:g>
|
12821 | </svg:g>
|
12822 | `,
|
12823 | changeDetection: ChangeDetectionStrategy.OnPush
|
12824 | },] }
|
12825 | ];
|
12826 | PieGridSeriesComponent.ctorParameters = () => [
|
12827 | { type: ElementRef }
|
12828 | ];
|
12829 | PieGridSeriesComponent.propDecorators = {
|
12830 | colors: [{ type: Input }],
|
12831 | data: [{ type: Input }],
|
12832 | innerRadius: [{ type: Input }],
|
12833 | outerRadius: [{ type: Input }],
|
12834 | animations: [{ type: Input }],
|
12835 | select: [{ type: Output }],
|
12836 | activate: [{ type: Output }],
|
12837 | deactivate: [{ type: Output }]
|
12838 | };
|
12839 |
|
12840 | class PieSeriesComponent {
|
12841 | constructor() {
|
12842 | this.series = [];
|
12843 | this.innerRadius = 60;
|
12844 | this.outerRadius = 80;
|
12845 | this.trimLabels = true;
|
12846 | this.maxLabelLength = 10;
|
12847 | this.tooltipDisabled = false;
|
12848 | this.animations = true;
|
12849 | this.select = new EventEmitter();
|
12850 | this.activate = new EventEmitter();
|
12851 | this.deactivate = new EventEmitter();
|
12852 | this.dblclick = new EventEmitter();
|
12853 | this.placementTypes = PlacementTypes;
|
12854 | this.styleTypes = StyleTypes;
|
12855 | }
|
12856 | ngOnChanges(changes) {
|
12857 | this.update();
|
12858 | }
|
12859 | update() {
|
12860 | const pieGenerator = pie()
|
12861 | .value(d => d.value)
|
12862 | .sort(null);
|
12863 | const arcData = pieGenerator(this.series);
|
12864 | this.max = max(arcData, d => {
|
12865 | return d.value;
|
12866 | });
|
12867 | this.data = this.calculateLabelPositions(arcData);
|
12868 | this.tooltipText = this.tooltipText || this.defaultTooltipText;
|
12869 | }
|
12870 | midAngle(d) {
|
12871 | return d.startAngle + (d.endAngle - d.startAngle) / 2;
|
12872 | }
|
12873 | outerArc() {
|
12874 | const factor = 1.5;
|
12875 | return arc()
|
12876 | .innerRadius(this.outerRadius * factor)
|
12877 | .outerRadius(this.outerRadius * factor);
|
12878 | }
|
12879 | calculateLabelPositions(pieData) {
|
12880 | const factor = 1.5;
|
12881 | const minDistance = 10;
|
12882 | const labelPositions = pieData;
|
12883 | labelPositions.forEach(d => {
|
12884 | d.pos = this.outerArc().centroid(d);
|
12885 | d.pos[0] = factor * this.outerRadius * (this.midAngle(d) < Math.PI ? 1 : -1);
|
12886 | });
|
12887 | for (let i = 0; i < labelPositions.length - 1; i++) {
|
12888 | const a = labelPositions[i];
|
12889 | if (!this.labelVisible(a)) {
|
12890 | continue;
|
12891 | }
|
12892 | for (let j = i + 1; j < labelPositions.length; j++) {
|
12893 | const b = labelPositions[j];
|
12894 | if (!this.labelVisible(b)) {
|
12895 | continue;
|
12896 | }
|
12897 |
|
12898 | if (b.pos[0] * a.pos[0] > 0) {
|
12899 |
|
12900 | const o = minDistance - Math.abs(b.pos[1] - a.pos[1]);
|
12901 | if (o > 0) {
|
12902 |
|
12903 | b.pos[1] += Math.sign(b.pos[0]) * o;
|
12904 | }
|
12905 | }
|
12906 | }
|
12907 | }
|
12908 | return labelPositions;
|
12909 | }
|
12910 | labelVisible(myArc) {
|
12911 | return this.showLabels && myArc.endAngle - myArc.startAngle > Math.PI / 30;
|
12912 | }
|
12913 | getTooltipTitle(a) {
|
12914 | return this.tooltipTemplate ? undefined : this.tooltipText(a);
|
12915 | }
|
12916 | labelText(myArc) {
|
12917 | if (this.labelFormatting) {
|
12918 | return this.labelFormatting(myArc.data.name);
|
12919 | }
|
12920 | return this.label(myArc);
|
12921 | }
|
12922 | label(myArc) {
|
12923 | return formatLabel(myArc.data.name);
|
12924 | }
|
12925 | defaultTooltipText(myArc) {
|
12926 | const label = this.label(myArc);
|
12927 | const val = formatLabel(myArc.data.value);
|
12928 | return `
|
12929 | <span class="tooltip-label">${escapeLabel(label)}</span>
|
12930 | <span class="tooltip-val">${val}</span>
|
12931 | `;
|
12932 | }
|
12933 | color(myArc) {
|
12934 | return this.colors.getColor(this.label(myArc));
|
12935 | }
|
12936 | trackBy(index, item) {
|
12937 | return item.data.name;
|
12938 | }
|
12939 | onClick(data) {
|
12940 | this.select.emit(data);
|
12941 | }
|
12942 | isActive(entry) {
|
12943 | if (!this.activeEntries)
|
12944 | return false;
|
12945 | const item = this.activeEntries.find(d => {
|
12946 | return entry.name === d.name && entry.series === d.series;
|
12947 | });
|
12948 | return item !== undefined;
|
12949 | }
|
12950 | }
|
12951 | PieSeriesComponent.decorators = [
|
12952 | { type: Component, args: [{
|
12953 | selector: 'g[ngx-charts-pie-series]',
|
12954 | template: `
|
12955 | <svg:g *ngFor="let arc of data; trackBy: trackBy">
|
12956 | <svg:g
|
12957 | ngx-charts-pie-label
|
12958 | *ngIf="labelVisible(arc)"
|
12959 | [data]="arc"
|
12960 | [radius]="outerRadius"
|
12961 | [color]="color(arc)"
|
12962 | [label]="labelText(arc)"
|
12963 | [labelTrim]="trimLabels"
|
12964 | [labelTrimSize]="maxLabelLength"
|
12965 | [max]="max"
|
12966 | [value]="arc.value"
|
12967 | [explodeSlices]="explodeSlices"
|
12968 | [animations]="animations"
|
12969 | ></svg:g>
|
12970 | <svg:g
|
12971 | ngx-charts-pie-arc
|
12972 | [startAngle]="arc.startAngle"
|
12973 | [endAngle]="arc.endAngle"
|
12974 | [innerRadius]="innerRadius"
|
12975 | [outerRadius]="outerRadius"
|
12976 | [fill]="color(arc)"
|
12977 | [value]="arc.data.value"
|
12978 | [gradient]="gradient"
|
12979 | [data]="arc.data"
|
12980 | [max]="max"
|
12981 | [explodeSlices]="explodeSlices"
|
12982 | [isActive]="isActive(arc.data)"
|
12983 | [animate]="animations"
|
12984 | (select)="onClick($event)"
|
12985 | (activate)="activate.emit($event)"
|
12986 | (deactivate)="deactivate.emit($event)"
|
12987 | (dblclick)="dblclick.emit($event)"
|
12988 | ngx-tooltip
|
12989 | [tooltipDisabled]="tooltipDisabled"
|
12990 | [tooltipPlacement]="placementTypes.Top"
|
12991 | [tooltipType]="styleTypes.tooltip"
|
12992 | [tooltipTitle]="getTooltipTitle(arc)"
|
12993 | [tooltipTemplate]="tooltipTemplate"
|
12994 | [tooltipContext]="arc.data"
|
12995 | ></svg:g>
|
12996 | </svg:g>
|
12997 | `,
|
12998 | changeDetection: ChangeDetectionStrategy.OnPush
|
12999 | },] }
|
13000 | ];
|
13001 | PieSeriesComponent.propDecorators = {
|
13002 | colors: [{ type: Input }],
|
13003 | series: [{ type: Input }],
|
13004 | dims: [{ type: Input }],
|
13005 | innerRadius: [{ type: Input }],
|
13006 | outerRadius: [{ type: Input }],
|
13007 | explodeSlices: [{ type: Input }],
|
13008 | showLabels: [{ type: Input }],
|
13009 | gradient: [{ type: Input }],
|
13010 | activeEntries: [{ type: Input }],
|
13011 | labelFormatting: [{ type: Input }],
|
13012 | trimLabels: [{ type: Input }],
|
13013 | maxLabelLength: [{ type: Input }],
|
13014 | tooltipText: [{ type: Input }],
|
13015 | tooltipDisabled: [{ type: Input }],
|
13016 | tooltipTemplate: [{ type: Input }],
|
13017 | animations: [{ type: Input }],
|
13018 | select: [{ type: Output }],
|
13019 | activate: [{ type: Output }],
|
13020 | deactivate: [{ type: Output }],
|
13021 | dblclick: [{ type: Output }]
|
13022 | };
|
13023 |
|
13024 | class PieChartModule {
|
13025 | }
|
13026 | PieChartModule.decorators = [
|
13027 | { type: NgModule, args: [{
|
13028 | imports: [ChartCommonModule],
|
13029 | declarations: [
|
13030 | AdvancedPieChartComponent,
|
13031 | PieLabelComponent,
|
13032 | PieArcComponent,
|
13033 | PieChartComponent,
|
13034 | PieGridComponent,
|
13035 | PieGridSeriesComponent,
|
13036 | PieSeriesComponent
|
13037 | ],
|
13038 | exports: [
|
13039 | AdvancedPieChartComponent,
|
13040 | PieLabelComponent,
|
13041 | PieArcComponent,
|
13042 | PieChartComponent,
|
13043 | PieGridComponent,
|
13044 | PieGridSeriesComponent,
|
13045 | PieSeriesComponent
|
13046 | ]
|
13047 | },] }
|
13048 | ];
|
13049 |
|
13050 | class PolarChartModule {
|
13051 | }
|
13052 | PolarChartModule.decorators = [
|
13053 | { type: NgModule, args: [{
|
13054 | imports: [ChartCommonModule, PieChartModule, LineChartModule],
|
13055 | declarations: [PolarChartComponent, PolarSeriesComponent],
|
13056 | exports: [PolarChartComponent, PolarSeriesComponent]
|
13057 | },] }
|
13058 | ];
|
13059 |
|
13060 | function calculateTextWidth(fontFamilyKey, text, defaultWidth = 8) {
|
13061 | return text.split('').reduce((acc, curr) => {
|
13062 | const width = fontFamilyKey[curr] || defaultWidth;
|
13063 | return acc + width;
|
13064 | }, 0);
|
13065 | }
|
13066 |
|
13067 | const VERDANA_FONT_WIDTHS_16_PX = {
|
13068 | '0': 10,
|
13069 | '1': 10,
|
13070 | '2': 10,
|
13071 | '3': 10,
|
13072 | '4': 10,
|
13073 | '5': 10,
|
13074 | '6': 10,
|
13075 | '7': 10,
|
13076 | '8': 10,
|
13077 | '9': 10,
|
13078 | A: 11,
|
13079 | B: 11,
|
13080 | C: 11,
|
13081 | D: 12,
|
13082 | E: 10,
|
13083 | F: 9,
|
13084 | G: 12,
|
13085 | H: 12,
|
13086 | I: 7,
|
13087 | J: 7,
|
13088 | K: 11,
|
13089 | L: 9,
|
13090 | M: 13,
|
13091 | N: 12,
|
13092 | O: 13,
|
13093 | P: 10,
|
13094 | Q: 13,
|
13095 | R: 11,
|
13096 | S: 11,
|
13097 | T: 10,
|
13098 | U: 12,
|
13099 | V: 11,
|
13100 | W: 16,
|
13101 | X: 11,
|
13102 | Y: 10,
|
13103 | Z: 11,
|
13104 | a: 10,
|
13105 | b: 10,
|
13106 | c: 8,
|
13107 | d: 10,
|
13108 | e: 10,
|
13109 | f: 6,
|
13110 | g: 10,
|
13111 | h: 10,
|
13112 | i: 4,
|
13113 | j: 6,
|
13114 | k: 9,
|
13115 | l: 4,
|
13116 | m: 16,
|
13117 | n: 10,
|
13118 | o: 10,
|
13119 | p: 10,
|
13120 | q: 10,
|
13121 | r: 7,
|
13122 | s: 8,
|
13123 | t: 6,
|
13124 | u: 10,
|
13125 | v: 9,
|
13126 | w: 13,
|
13127 | x: 9,
|
13128 | y: 9,
|
13129 | z: 8,
|
13130 | '!': 6,
|
13131 | '@': 16,
|
13132 | '#': 13,
|
13133 | $: 10,
|
13134 | '%': 17,
|
13135 | '^': 13,
|
13136 | '&': 12,
|
13137 | '*': 10,
|
13138 | '(': 7,
|
13139 | ')': 7,
|
13140 | _: 10,
|
13141 | '-': 7,
|
13142 | '+': 13,
|
13143 | '=': 13,
|
13144 | ',': 6,
|
13145 | '.': 6,
|
13146 | '/': 7,
|
13147 | "'": 4,
|
13148 | ':': 7,
|
13149 | '|': 7,
|
13150 | '?': 9,
|
13151 | ';': 7,
|
13152 | '<': 13,
|
13153 | '>': 13
|
13154 | };
|
13155 |
|
13156 | class CardComponent {
|
13157 | constructor(element, cd, zone, platformId) {
|
13158 | this.cd = cd;
|
13159 | this.zone = zone;
|
13160 | this.platformId = platformId;
|
13161 | this.animations = true;
|
13162 | this.select = new EventEmitter();
|
13163 | this.value = '';
|
13164 | this.textFontSize = 12;
|
13165 | this.textTransform = '';
|
13166 | this.initialized = false;
|
13167 | this.bandHeight = 10;
|
13168 | this.textPadding = [10, 20, 5, 20];
|
13169 | this.labelFontSize = 15;
|
13170 | this.element = element.nativeElement;
|
13171 | }
|
13172 | ngOnChanges(changes) {
|
13173 | this.update();
|
13174 | }
|
13175 | ngOnInit() {
|
13176 | if (isPlatformServer(this.platformId)) {
|
13177 | this.scaleTextSSR();
|
13178 | }
|
13179 | }
|
13180 | ngOnDestroy() {
|
13181 | if (isPlatformBrowser(this.platformId)) {
|
13182 | cancelAnimationFrame(this.animationReq);
|
13183 | }
|
13184 | }
|
13185 | update() {
|
13186 | this.zone.run(() => {
|
13187 | const hasValue = this.data && typeof this.data.value !== 'undefined';
|
13188 | const valueFormatting = this.valueFormatting || (card => card.value.toLocaleString());
|
13189 | const labelFormatting = this.labelFormatting || (card => escapeLabel(trimLabel(card.label, 55)));
|
13190 | this.transform = `translate(${this.x} , ${this.y})`;
|
13191 | this.textWidth = Math.max(0, this.width) - this.textPadding[1] - this.textPadding[3];
|
13192 | this.cardWidth = Math.max(0, this.width);
|
13193 | this.cardHeight = Math.max(0, this.height);
|
13194 | this.label = this.label ? this.label : this.data.name;
|
13195 | const cardData = {
|
13196 | label: this.label,
|
13197 | data: this.data,
|
13198 | value: this.data.value
|
13199 | };
|
13200 | this.formattedLabel = labelFormatting(cardData);
|
13201 | this.transformBand = `translate(0 , ${this.cardHeight - this.bandHeight})`;
|
13202 | const value = hasValue ? valueFormatting(cardData) : '';
|
13203 | this.value = this.paddedValue(value);
|
13204 | this.setPadding();
|
13205 | this.bandPath = roundedRect(0, 0, this.cardWidth, this.bandHeight, 3, [false, false, true, true]);
|
13206 | setTimeout(() => {
|
13207 | if (isPlatformBrowser(this.platformId)) {
|
13208 | this.scaleText();
|
13209 | }
|
13210 | this.value = value;
|
13211 | if (hasValue && !this.initialized) {
|
13212 | setTimeout(() => this.startCount(), 20);
|
13213 | }
|
13214 | }, 8);
|
13215 | });
|
13216 | }
|
13217 | paddedValue(value) {
|
13218 | if (this.medianSize && this.medianSize > value.length) {
|
13219 | value += '\u2007'.repeat(this.medianSize - value.length);
|
13220 | }
|
13221 | return value;
|
13222 | }
|
13223 | startCount() {
|
13224 | if (!this.initialized && this.animations) {
|
13225 | cancelAnimationFrame(this.animationReq);
|
13226 | const val = this.data.value;
|
13227 | const decs = decimalChecker(val);
|
13228 | const valueFormatting = this.valueFormatting || (card => card.value.toLocaleString());
|
13229 | const callback = ({ value, finished }) => {
|
13230 | this.zone.run(() => {
|
13231 | value = finished ? val : value;
|
13232 | this.value = valueFormatting({ label: this.label, data: this.data, value });
|
13233 | if (!finished) {
|
13234 | this.value = this.paddedValue(this.value);
|
13235 | }
|
13236 | this.cd.markForCheck();
|
13237 | });
|
13238 | };
|
13239 | this.animationReq = count(0, val, decs, 1, callback);
|
13240 | this.initialized = true;
|
13241 | }
|
13242 | }
|
13243 | scaleText() {
|
13244 | this.zone.run(() => {
|
13245 | const { width, height } = this.textEl.nativeElement.getBoundingClientRect();
|
13246 | if (width === 0 || height === 0) {
|
13247 | return;
|
13248 | }
|
13249 | const textPadding = (this.textPadding[1] = this.textPadding[3] = this.cardWidth / 8);
|
13250 | const availableWidth = this.cardWidth - 2 * textPadding;
|
13251 | const availableHeight = this.cardHeight / 3;
|
13252 | const resizeScale = Math.min(availableWidth / width, availableHeight / height);
|
13253 | this.textFontSize = Math.floor(this.textFontSize * resizeScale);
|
13254 | this.labelFontSize = Math.min(this.textFontSize, 15);
|
13255 | this.setPadding();
|
13256 | this.cd.markForCheck();
|
13257 | });
|
13258 | }
|
13259 | scaleTextSSR() {
|
13260 | const width = calculateTextWidth(VERDANA_FONT_WIDTHS_16_PX, this.value, 10);
|
13261 | const height = 18;
|
13262 | const textPadding = (this.textPadding[1] = this.textPadding[3] = this.cardWidth / 8);
|
13263 | const availableWidth = this.cardWidth - 2 * textPadding;
|
13264 | const availableHeight = this.cardHeight / 3;
|
13265 | const resizeScale = Math.min(availableWidth / width, availableHeight / height);
|
13266 | this.textFontSize = Math.floor(this.textFontSize * resizeScale);
|
13267 | this.labelFontSize = Math.min(this.textFontSize, 15);
|
13268 | this.setPadding();
|
13269 | }
|
13270 | setPadding() {
|
13271 | this.textPadding[1] = this.textPadding[3] = this.cardWidth / 8;
|
13272 | const padding = this.cardHeight / 2;
|
13273 | this.textPadding[0] = padding - this.textFontSize - this.labelFontSize / 2;
|
13274 | this.textPadding[2] = padding - this.labelFontSize;
|
13275 | }
|
13276 | onClick() {
|
13277 | this.select.emit(this.data);
|
13278 | }
|
13279 | }
|
13280 | CardComponent.decorators = [
|
13281 | { type: Component, args: [{
|
13282 | selector: 'g[ngx-charts-card]',
|
13283 | template: `
|
13284 | <svg:g [attr.transform]="transform" class="cell" (click)="onClick()">
|
13285 | <svg:rect class="card" [style.fill]="color" [attr.width]="cardWidth" [attr.height]="cardHeight" rx="3" ry="3" />
|
13286 | <svg:path
|
13287 | *ngIf="bandColor && bandColor !== color"
|
13288 | class="card-band"
|
13289 | [attr.fill]="bandColor"
|
13290 | [attr.transform]="transformBand"
|
13291 | stroke="none"
|
13292 | [attr.d]="bandPath"
|
13293 | />
|
13294 | <title>{{ label }}</title>
|
13295 | <svg:foreignObject
|
13296 | class="trimmed-label"
|
13297 | x="5"
|
13298 | [attr.x]="textPadding[3]"
|
13299 | [attr.y]="cardHeight - textPadding[2]"
|
13300 | [attr.width]="textWidth"
|
13301 | [attr.height]="labelFontSize + textPadding[2]"
|
13302 | alignment-baseline="hanging"
|
13303 | >
|
13304 | <xhtml:p
|
13305 | [style.color]="textColor"
|
13306 | [style.fontSize.px]="labelFontSize"
|
13307 | [style.lineHeight.px]="labelFontSize"
|
13308 | [innerHTML]="formattedLabel"
|
13309 | >
|
13310 | </xhtml:p>
|
13311 | </svg:foreignObject>
|
13312 | <svg:text
|
13313 | #textEl
|
13314 | class="value-text"
|
13315 | [attr.x]="textPadding[3]"
|
13316 | [attr.y]="textPadding[0]"
|
13317 | [style.fill]="textColor"
|
13318 | text-anchor="start"
|
13319 | alignment-baseline="hanging"
|
13320 | [style.font-size.pt]="textFontSize"
|
13321 | >
|
13322 | {{ value }}
|
13323 | </svg:text>
|
13324 | </svg:g>
|
13325 | `,
|
13326 | changeDetection: ChangeDetectionStrategy.OnPush
|
13327 | },] }
|
13328 | ];
|
13329 | CardComponent.ctorParameters = () => [
|
13330 | { type: ElementRef },
|
13331 | { type: ChangeDetectorRef },
|
13332 | { type: NgZone },
|
13333 | { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
13334 | ];
|
13335 | CardComponent.propDecorators = {
|
13336 | color: [{ type: Input }],
|
13337 | bandColor: [{ type: Input }],
|
13338 | textColor: [{ type: Input }],
|
13339 | x: [{ type: Input }],
|
13340 | y: [{ type: Input }],
|
13341 | width: [{ type: Input }],
|
13342 | height: [{ type: Input }],
|
13343 | label: [{ type: Input }],
|
13344 | data: [{ type: Input }],
|
13345 | medianSize: [{ type: Input }],
|
13346 | valueFormatting: [{ type: Input }],
|
13347 | labelFormatting: [{ type: Input }],
|
13348 | animations: [{ type: Input }],
|
13349 | select: [{ type: Output }],
|
13350 | textEl: [{ type: ViewChild, args: ['textEl', { static: false },] }]
|
13351 | };
|
13352 |
|
13353 |
|
13354 |
|
13355 |
|
13356 |
|
13357 |
|
13358 | function hexToRgb(value) {
|
13359 |
|
13360 | return d3_color.rgb(value);
|
13361 | }
|
13362 |
|
13363 |
|
13364 |
|
13365 |
|
13366 |
|
13367 |
|
13368 | function invertColor(value) {
|
13369 | const color = d3_color.rgb(value);
|
13370 | const { r, g, b, opacity } = color;
|
13371 | if (opacity === 0) {
|
13372 | return color.toString();
|
13373 | }
|
13374 | const yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
13375 | const depth = yiq >= 128 ? -0.8 : 0.8;
|
13376 | return shadeRGBColor(color, depth);
|
13377 | }
|
13378 |
|
13379 |
|
13380 |
|
13381 |
|
13382 |
|
13383 |
|
13384 |
|
13385 | function shadeRGBColor({ r, g, b }, percent) {
|
13386 | const t = percent < 0 ? 0 : 255;
|
13387 | const p = percent < 0 ? percent * -1 : percent;
|
13388 | r = Math.round((t - r) * p) + r;
|
13389 | g = Math.round((t - g) * p) + g;
|
13390 | b = Math.round((t - b) * p) + b;
|
13391 | return `rgb(${r}, ${g}, ${b})`;
|
13392 | }
|
13393 |
|
13394 | class CardSeriesComponent {
|
13395 | constructor() {
|
13396 | this.innerPadding = 15;
|
13397 | this.emptyColor = 'rgba(0, 0, 0, 0)';
|
13398 | this.animations = true;
|
13399 | this.select = new EventEmitter();
|
13400 | }
|
13401 | ngOnChanges(changes) {
|
13402 | this.update();
|
13403 | }
|
13404 | update() {
|
13405 | if (this.data.length > 2) {
|
13406 | const valueFormatting = this.valueFormatting || (card => card.value.toLocaleString());
|
13407 | const sortedLengths = this.data
|
13408 | .map(d => {
|
13409 | const hasValue = d && d.data && typeof d.data.value !== 'undefined' && d.data.value !== null;
|
13410 | return hasValue
|
13411 | ? valueFormatting({
|
13412 | data: d.data,
|
13413 | label: d ? d.data.name : '',
|
13414 | value: d && d.data ? d.data.value : ''
|
13415 | }).length
|
13416 | : 0;
|
13417 | })
|
13418 | .sort((a, b) => b - a);
|
13419 | const idx = Math.ceil(this.data.length / 2);
|
13420 | this.medianSize = sortedLengths[idx];
|
13421 | }
|
13422 | const cards = this.getCards();
|
13423 | this.cards = cards.filter(d => d.data.value !== null);
|
13424 | this.emptySlots = cards.filter(d => d.data.value === null);
|
13425 | }
|
13426 | getCards() {
|
13427 | const yPadding = typeof this.innerPadding === 'number' ? this.innerPadding : this.innerPadding[0] + this.innerPadding[2];
|
13428 | const xPadding = typeof this.innerPadding === 'number' ? this.innerPadding : this.innerPadding[1] + this.innerPadding[3];
|
13429 | return this.data.map((d, index) => {
|
13430 | let label = d.data.name;
|
13431 | if (label && label.constructor.name === 'Date') {
|
13432 | label = label.toLocaleDateString();
|
13433 | }
|
13434 | else {
|
13435 | label = label ? label.toLocaleString() : label;
|
13436 | }
|
13437 | const value = d.data.value;
|
13438 | const valueColor = label ? this.colors.getColor(label) : this.emptyColor;
|
13439 | const color = this.cardColor || valueColor || '#000';
|
13440 | return {
|
13441 | x: d.x,
|
13442 | y: d.y,
|
13443 | width: d.width - xPadding,
|
13444 | height: d.height - yPadding,
|
13445 | color,
|
13446 | bandColor: this.bandColor || valueColor,
|
13447 | textColor: this.textColor || invertColor(color),
|
13448 | label,
|
13449 | data: d.data,
|
13450 | tooltipText: `${label}: ${value}`
|
13451 | };
|
13452 | });
|
13453 | }
|
13454 | trackBy(index, card) {
|
13455 | return card.label;
|
13456 | }
|
13457 | onClick(data) {
|
13458 | this.select.emit(data);
|
13459 | }
|
13460 | }
|
13461 | CardSeriesComponent.decorators = [
|
13462 | { type: Component, args: [{
|
13463 | selector: 'g[ngx-charts-card-series]',
|
13464 | template: `
|
13465 | <svg:rect
|
13466 | *ngFor="let c of emptySlots; trackBy: trackBy"
|
13467 | class="card-empty"
|
13468 | [attr.x]="c.x"
|
13469 | [attr.y]="c.y"
|
13470 | [style.fill]="emptyColor"
|
13471 | [attr.width]="c.width"
|
13472 | [attr.height]="c.height"
|
13473 | rx="3"
|
13474 | ry="3"
|
13475 | />
|
13476 | <svg:g
|
13477 | ngx-charts-card
|
13478 | *ngFor="let c of cards; trackBy: trackBy"
|
13479 | [x]="c.x"
|
13480 | [y]="c.y"
|
13481 | [width]="c.width"
|
13482 | [height]="c.height"
|
13483 | [color]="c.color"
|
13484 | [bandColor]="c.bandColor"
|
13485 | [textColor]="c.textColor"
|
13486 | [data]="c.data"
|
13487 | [label]="c.label"
|
13488 | [medianSize]="medianSize"
|
13489 | [valueFormatting]="valueFormatting"
|
13490 | [labelFormatting]="labelFormatting"
|
13491 | [animations]="animations"
|
13492 | (select)="onClick($event)"
|
13493 | />
|
13494 | `,
|
13495 | changeDetection: ChangeDetectionStrategy.OnPush
|
13496 | },] }
|
13497 | ];
|
13498 | CardSeriesComponent.propDecorators = {
|
13499 | data: [{ type: Input }],
|
13500 | dims: [{ type: Input }],
|
13501 | colors: [{ type: Input }],
|
13502 | innerPadding: [{ type: Input }],
|
13503 | cardColor: [{ type: Input }],
|
13504 | bandColor: [{ type: Input }],
|
13505 | emptyColor: [{ type: Input }],
|
13506 | textColor: [{ type: Input }],
|
13507 | valueFormatting: [{ type: Input }],
|
13508 | labelFormatting: [{ type: Input }],
|
13509 | animations: [{ type: Input }],
|
13510 | select: [{ type: Output }]
|
13511 | };
|
13512 |
|
13513 | class NumberCardComponent extends BaseChartComponent {
|
13514 | constructor() {
|
13515 | super(...arguments);
|
13516 | this.emptyColor = 'rgba(0, 0, 0, 0)';
|
13517 | this.innerPadding = 15;
|
13518 | this.margin = [10, 10, 10, 10];
|
13519 | }
|
13520 | get clickable() {
|
13521 | return !!this.select.observers.length;
|
13522 | }
|
13523 | update() {
|
13524 | super.update();
|
13525 | this.dims = calculateViewDimensions({
|
13526 | width: this.width,
|
13527 | height: this.height,
|
13528 | margins: this.margin
|
13529 | });
|
13530 | this.formatDates();
|
13531 | this.domain = this.getDomain();
|
13532 | this.setColors();
|
13533 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
13534 | const size = gridSize(this.dims, this.results.length, 150);
|
13535 | const N = size[0] * size[1];
|
13536 | const data = this.results.slice();
|
13537 | while (data.length < N) {
|
13538 | data.push({ value: null });
|
13539 | }
|
13540 | this.data = gridLayout(this.dims, data, 150, this.designatedTotal);
|
13541 | }
|
13542 | getDomain() {
|
13543 | return this.results.map(d => d.label);
|
13544 | }
|
13545 | onClick(data) {
|
13546 | this.select.emit(data);
|
13547 | }
|
13548 | setColors() {
|
13549 | this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
13550 | }
|
13551 | }
|
13552 | NumberCardComponent.decorators = [
|
13553 | { type: Component, args: [{
|
13554 | selector: 'ngx-charts-number-card',
|
13555 | template: `
|
13556 | <ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
13557 | <svg:g [attr.transform]="transform" class="number-card chart" [class.clickable]="clickable">
|
13558 | <svg:g
|
13559 | ngx-charts-card-series
|
13560 | [colors]="colors"
|
13561 | [cardColor]="cardColor"
|
13562 | [bandColor]="bandColor"
|
13563 | [textColor]="textColor"
|
13564 | [emptyColor]="emptyColor"
|
13565 | [data]="data"
|
13566 | [dims]="dims"
|
13567 | [innerPadding]="innerPadding"
|
13568 | [valueFormatting]="valueFormatting"
|
13569 | [labelFormatting]="labelFormatting"
|
13570 | [animations]="animations"
|
13571 | (select)="onClick($event)"
|
13572 | />
|
13573 | </svg:g>
|
13574 | </ngx-charts-chart>
|
13575 | `,
|
13576 | encapsulation: ViewEncapsulation.None,
|
13577 | changeDetection: ChangeDetectionStrategy.OnPush,
|
13578 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
13579 | },] }
|
13580 | ];
|
13581 | NumberCardComponent.propDecorators = {
|
13582 | cardColor: [{ type: Input }],
|
13583 | bandColor: [{ type: Input }],
|
13584 | emptyColor: [{ type: Input }],
|
13585 | innerPadding: [{ type: Input }],
|
13586 | textColor: [{ type: Input }],
|
13587 | valueFormatting: [{ type: Input }],
|
13588 | labelFormatting: [{ type: Input }],
|
13589 | designatedTotal: [{ type: Input }]
|
13590 | };
|
13591 |
|
13592 | class NumberCardModule {
|
13593 | }
|
13594 | NumberCardModule.decorators = [
|
13595 | { type: NgModule, args: [{
|
13596 | imports: [ChartCommonModule],
|
13597 | declarations: [CardComponent, CardSeriesComponent, NumberCardComponent],
|
13598 | exports: [CardComponent, CardSeriesComponent, NumberCardComponent]
|
13599 | },] }
|
13600 | ];
|
13601 |
|
13602 | class TreeMapCellComponent {
|
13603 | constructor(element) {
|
13604 | this.gradient = false;
|
13605 | this.animations = true;
|
13606 | this.select = new EventEmitter();
|
13607 | this.initialized = false;
|
13608 | this.orientation = BarOrientation;
|
13609 | this.element = element.nativeElement;
|
13610 | }
|
13611 | ngOnChanges() {
|
13612 | this.update();
|
13613 | this.valueFormatting = this.valueFormatting || (value => value.toLocaleString());
|
13614 | const labelFormatting = this.labelFormatting || (cell => escapeLabel(trimLabel(cell.label, 55)));
|
13615 | const cellData = {
|
13616 | data: this.data,
|
13617 | label: this.label,
|
13618 | value: this.value
|
13619 | };
|
13620 | this.formattedValue = this.valueFormatting(cellData.value);
|
13621 | this.formattedLabel = labelFormatting(cellData);
|
13622 | this.gradientId = 'grad' + id().toString();
|
13623 | this.gradientUrl = `url(#${this.gradientId})`;
|
13624 | this.gradientStops = this.getGradientStops();
|
13625 | }
|
13626 | update() {
|
13627 | if (this.initialized) {
|
13628 | this.animateToCurrentForm();
|
13629 | }
|
13630 | else {
|
13631 | if (this.animations) {
|
13632 | this.loadAnimation();
|
13633 | }
|
13634 | this.initialized = true;
|
13635 | }
|
13636 | }
|
13637 | loadAnimation() {
|
13638 | const node = select(this.element).select('.cell');
|
13639 | node.attr('opacity', 0).attr('x', this.x).attr('y', this.y);
|
13640 | this.animateToCurrentForm();
|
13641 | }
|
13642 | getTextColor() {
|
13643 | return invertColor(this.fill);
|
13644 | }
|
13645 | animateToCurrentForm() {
|
13646 | const node = select(this.element).select('.cell');
|
13647 | if (this.animations) {
|
13648 | node
|
13649 | .transition()
|
13650 | .duration(750)
|
13651 | .attr('opacity', 1)
|
13652 | .attr('x', this.x)
|
13653 | .attr('y', this.y)
|
13654 | .attr('width', this.width)
|
13655 | .attr('height', this.height);
|
13656 | }
|
13657 | else {
|
13658 | node.attr('opacity', 1).attr('x', this.x).attr('y', this.y).attr('width', this.width).attr('height', this.height);
|
13659 | }
|
13660 | }
|
13661 | onClick() {
|
13662 | this.select.emit(this.data);
|
13663 | }
|
13664 | getGradientStops() {
|
13665 | return [
|
13666 | {
|
13667 | offset: 0,
|
13668 | color: this.fill,
|
13669 | opacity: 0.3
|
13670 | },
|
13671 | {
|
13672 | offset: 100,
|
13673 | color: this.fill,
|
13674 | opacity: 1
|
13675 | }
|
13676 | ];
|
13677 | }
|
13678 | }
|
13679 | TreeMapCellComponent.decorators = [
|
13680 | { type: Component, args: [{
|
13681 | selector: 'g[ngx-charts-tree-map-cell]',
|
13682 | template: `
|
13683 | <svg:g>
|
13684 | <defs *ngIf="gradient">
|
13685 | <svg:g
|
13686 | ngx-charts-svg-linear-gradient
|
13687 | [orientation]="orientation.Vertical"
|
13688 | [name]="gradientId"
|
13689 | [stops]="gradientStops"
|
13690 | />
|
13691 | </defs>
|
13692 | <svg:rect
|
13693 | [attr.fill]="gradient ? gradientUrl : fill"
|
13694 | [attr.width]="width"
|
13695 | [attr.height]="height"
|
13696 | [attr.x]="x"
|
13697 | [attr.y]="y"
|
13698 | class="cell"
|
13699 | (click)="onClick()"
|
13700 | />
|
13701 | <svg:foreignObject
|
13702 | *ngIf="width >= 70 && height >= 35"
|
13703 | [attr.x]="x"
|
13704 | [attr.y]="y"
|
13705 | [attr.width]="width"
|
13706 | [attr.height]="height"
|
13707 | class="treemap-label"
|
13708 | [style.pointer-events]="'none'"
|
13709 | >
|
13710 | <xhtml:p [style.color]="getTextColor()" [style.height]="height + 'px'" [style.width]="width + 'px'">
|
13711 | <xhtml:span class="treemap-label" [innerHTML]="formattedLabel"> </xhtml:span>
|
13712 | <xhtml:br />
|
13713 | <xhtml:span
|
13714 | *ngIf="animations"
|
13715 | class="treemap-val"
|
13716 | ngx-charts-count-up
|
13717 | [countTo]="value"
|
13718 | [valueFormatting]="valueFormatting"
|
13719 | >
|
13720 | </xhtml:span>
|
13721 | <xhtml:span *ngIf="!animations" class="treemap-val">
|
13722 | {{ formattedValue }}
|
13723 | </xhtml:span>
|
13724 | </xhtml:p>
|
13725 | </svg:foreignObject>
|
13726 | </svg:g>
|
13727 | `,
|
13728 | changeDetection: ChangeDetectionStrategy.OnPush
|
13729 | },] }
|
13730 | ];
|
13731 | TreeMapCellComponent.ctorParameters = () => [
|
13732 | { type: ElementRef }
|
13733 | ];
|
13734 | TreeMapCellComponent.propDecorators = {
|
13735 | data: [{ type: Input }],
|
13736 | fill: [{ type: Input }],
|
13737 | x: [{ type: Input }],
|
13738 | y: [{ type: Input }],
|
13739 | width: [{ type: Input }],
|
13740 | height: [{ type: Input }],
|
13741 | label: [{ type: Input }],
|
13742 | value: [{ type: Input }],
|
13743 | valueFormatting: [{ type: Input }],
|
13744 | labelFormatting: [{ type: Input }],
|
13745 | gradient: [{ type: Input }],
|
13746 | animations: [{ type: Input }],
|
13747 | select: [{ type: Output }]
|
13748 | };
|
13749 |
|
13750 | class TreeMapCellSeriesComponent {
|
13751 | constructor() {
|
13752 | this.gradient = false;
|
13753 | this.tooltipDisabled = false;
|
13754 | this.animations = true;
|
13755 | this.select = new EventEmitter();
|
13756 | this.styleTypes = StyleTypes;
|
13757 | this.placementTypes = PlacementTypes;
|
13758 | }
|
13759 | ngOnChanges(changes) {
|
13760 | this.cells = this.getCells();
|
13761 | }
|
13762 | getCells() {
|
13763 | return this.data.children
|
13764 | .filter(d => {
|
13765 | return d.depth === 1;
|
13766 | })
|
13767 | .map((d, index) => {
|
13768 | const label = d.id;
|
13769 | return {
|
13770 | data: d.data,
|
13771 | x: d.x0,
|
13772 | y: d.y0,
|
13773 | width: d.x1 - d.x0,
|
13774 | height: d.y1 - d.y0,
|
13775 | fill: this.colors.getColor(label),
|
13776 | label,
|
13777 | value: d.value
|
13778 | };
|
13779 | });
|
13780 | }
|
13781 | getTooltipText({ label, value }) {
|
13782 | return `
|
13783 | <span class="tooltip-label">${escapeLabel(label)}</span>
|
13784 | <span class="tooltip-val">${value.toLocaleString()}</span>
|
13785 | `;
|
13786 | }
|
13787 | onClick(data) {
|
13788 | this.select.emit(data);
|
13789 | }
|
13790 | trackBy(index, item) {
|
13791 | return item.label;
|
13792 | }
|
13793 | }
|
13794 | TreeMapCellSeriesComponent.decorators = [
|
13795 | { type: Component, args: [{
|
13796 | selector: 'g[ngx-charts-tree-map-cell-series]',
|
13797 | template: `
|
13798 | <svg:g
|
13799 | ngx-charts-tree-map-cell
|
13800 | *ngFor="let c of cells; trackBy: trackBy"
|
13801 | [data]="c.data"
|
13802 | [x]="c.x"
|
13803 | [y]="c.y"
|
13804 | [width]="c.width"
|
13805 | [height]="c.height"
|
13806 | [fill]="c.fill"
|
13807 | [label]="c.label"
|
13808 | [value]="c.value"
|
13809 | [valueFormatting]="valueFormatting"
|
13810 | [labelFormatting]="labelFormatting"
|
13811 | [gradient]="gradient"
|
13812 | [animations]="animations"
|
13813 | (select)="onClick($event)"
|
13814 | ngx-tooltip
|
13815 | [tooltipDisabled]="tooltipDisabled"
|
13816 | [tooltipPlacement]="placementTypes.Top"
|
13817 | [tooltipType]="styleTypes.tooltip"
|
13818 | [tooltipTitle]="tooltipTemplate ? undefined : getTooltipText(c)"
|
13819 | [tooltipTemplate]="tooltipTemplate"
|
13820 | [tooltipContext]="c.data"
|
13821 | ></svg:g>
|
13822 | `,
|
13823 | changeDetection: ChangeDetectionStrategy.OnPush
|
13824 | },] }
|
13825 | ];
|
13826 | TreeMapCellSeriesComponent.propDecorators = {
|
13827 | data: [{ type: Input }],
|
13828 | dims: [{ type: Input }],
|
13829 | colors: [{ type: Input }],
|
13830 | valueFormatting: [{ type: Input }],
|
13831 | labelFormatting: [{ type: Input }],
|
13832 | gradient: [{ type: Input }],
|
13833 | tooltipDisabled: [{ type: Input }],
|
13834 | tooltipTemplate: [{ type: Input }],
|
13835 | animations: [{ type: Input }],
|
13836 | select: [{ type: Output }]
|
13837 | };
|
13838 |
|
13839 | class TreeMapComponent extends BaseChartComponent {
|
13840 | constructor() {
|
13841 | super(...arguments);
|
13842 | this.tooltipDisabled = false;
|
13843 | this.gradient = false;
|
13844 | this.select = new EventEmitter();
|
13845 | this.margin = [10, 10, 10, 10];
|
13846 | }
|
13847 | update() {
|
13848 | super.update();
|
13849 | this.dims = calculateViewDimensions({
|
13850 | width: this.width,
|
13851 | height: this.height,
|
13852 | margins: this.margin
|
13853 | });
|
13854 | this.domain = this.getDomain();
|
13855 | this.treemap = treemap().size([this.dims.width, this.dims.height]);
|
13856 | const rootNode = {
|
13857 | name: 'root',
|
13858 | value: 0,
|
13859 | isRoot: true
|
13860 | };
|
13861 | const root = stratify()
|
13862 | .id(d => {
|
13863 | let label = d.name;
|
13864 | if (label.constructor.name === 'Date') {
|
13865 | label = label.toLocaleDateString();
|
13866 | }
|
13867 | else {
|
13868 | label = label.toLocaleString();
|
13869 | }
|
13870 | return label;
|
13871 | })
|
13872 | .parentId(d => (d.isRoot ? null : 'root'))([rootNode, ...this.results])
|
13873 | .sum(d => d.value);
|
13874 | this.data = this.treemap(root);
|
13875 | this.setColors();
|
13876 | this.transform = `translate(${this.dims.xOffset} , ${this.margin[0]})`;
|
13877 | }
|
13878 | getDomain() {
|
13879 | return this.results.map(d => d.name);
|
13880 | }
|
13881 | onClick(data) {
|
13882 | this.select.emit(data);
|
13883 | }
|
13884 | setColors() {
|
13885 | this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
13886 | }
|
13887 | }
|
13888 | TreeMapComponent.decorators = [
|
13889 | { type: Component, args: [{
|
13890 | selector: 'ngx-charts-tree-map',
|
13891 | template: `
|
13892 | <ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations">
|
13893 | <svg:g [attr.transform]="transform" class="tree-map chart">
|
13894 | <svg:g
|
13895 | ngx-charts-tree-map-cell-series
|
13896 | [colors]="colors"
|
13897 | [data]="data"
|
13898 | [dims]="dims"
|
13899 | [tooltipDisabled]="tooltipDisabled"
|
13900 | [tooltipTemplate]="tooltipTemplate"
|
13901 | [valueFormatting]="valueFormatting"
|
13902 | [labelFormatting]="labelFormatting"
|
13903 | [gradient]="gradient"
|
13904 | [animations]="animations"
|
13905 | (select)="onClick($event)"
|
13906 | />
|
13907 | </svg:g>
|
13908 | </ngx-charts-chart>
|
13909 | `,
|
13910 | encapsulation: ViewEncapsulation.None,
|
13911 | changeDetection: ChangeDetectionStrategy.OnPush,
|
13912 | 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"]
|
13913 | },] }
|
13914 | ];
|
13915 | TreeMapComponent.propDecorators = {
|
13916 | results: [{ type: Input }],
|
13917 | tooltipDisabled: [{ type: Input }],
|
13918 | valueFormatting: [{ type: Input }],
|
13919 | labelFormatting: [{ type: Input }],
|
13920 | gradient: [{ type: Input }],
|
13921 | select: [{ type: Output }],
|
13922 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }]
|
13923 | };
|
13924 |
|
13925 | class TreeMapModule {
|
13926 | }
|
13927 | TreeMapModule.decorators = [
|
13928 | { type: NgModule, args: [{
|
13929 | imports: [ChartCommonModule],
|
13930 | declarations: [TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent],
|
13931 | exports: [TreeMapCellComponent, TreeMapCellSeriesComponent, TreeMapComponent]
|
13932 | },] }
|
13933 | ];
|
13934 |
|
13935 | var ElementType;
|
13936 | (function (ElementType) {
|
13937 | ElementType["Value"] = "value";
|
13938 | ElementType["Units"] = "units";
|
13939 | })(ElementType || (ElementType = {}));
|
13940 | class LinearGaugeComponent extends BaseChartComponent {
|
13941 | constructor() {
|
13942 | super(...arguments);
|
13943 | this.min = 0;
|
13944 | this.max = 100;
|
13945 | this.value = 0;
|
13946 | this.margin = [10, 20, 10, 20];
|
13947 | this.valueResizeScale = 1;
|
13948 | this.unitsResizeScale = 1;
|
13949 | this.valueTextTransform = '';
|
13950 | this.valueTranslate = '';
|
13951 | this.unitsTextTransform = '';
|
13952 | this.unitsTranslate = '';
|
13953 | this.barOrientation = BarOrientation;
|
13954 | }
|
13955 | ngAfterViewInit() {
|
13956 | super.ngAfterViewInit();
|
13957 | setTimeout(() => {
|
13958 | this.scaleText(ElementType.Value);
|
13959 | this.scaleText(ElementType.Units);
|
13960 | });
|
13961 | }
|
13962 | update() {
|
13963 | super.update();
|
13964 | this.hasPreviousValue = this.previousValue !== undefined;
|
13965 | this.max = Math.max(this.max, this.value);
|
13966 | this.min = Math.min(this.min, this.value);
|
13967 | if (this.hasPreviousValue) {
|
13968 | this.max = Math.max(this.max, this.previousValue);
|
13969 | this.min = Math.min(this.min, this.previousValue);
|
13970 | }
|
13971 | this.dims = calculateViewDimensions({
|
13972 | width: this.width,
|
13973 | height: this.height,
|
13974 | margins: this.margin
|
13975 | });
|
13976 | this.valueDomain = this.getValueDomain();
|
13977 | this.valueScale = this.getValueScale();
|
13978 | this.displayValue = this.getDisplayValue();
|
13979 | this.setColors();
|
13980 | const xOffset = this.margin[3] + this.dims.width / 2;
|
13981 | const yOffset = this.margin[0] + this.dims.height / 2;
|
13982 | this.transform = `translate(${xOffset}, ${yOffset})`;
|
13983 | this.transformLine = `translate(${this.margin[3] + this.valueScale(this.previousValue)}, ${yOffset})`;
|
13984 | this.valueTranslate = `translate(0, -15)`;
|
13985 | this.unitsTranslate = `translate(0, 15)`;
|
13986 | if (isPlatformServer(this.platformId)) {
|
13987 | this.scaleTextSSR('value');
|
13988 | this.scaleTextSSR('units');
|
13989 | }
|
13990 | else {
|
13991 | setTimeout(() => this.scaleText(ElementType.Value), 50);
|
13992 | setTimeout(() => this.scaleText(ElementType.Units), 50);
|
13993 | }
|
13994 | }
|
13995 | getValueDomain() {
|
13996 | return [this.min, this.max];
|
13997 | }
|
13998 | getValueScale() {
|
13999 | return scaleLinear().range([0, this.dims.width]).domain(this.valueDomain);
|
14000 | }
|
14001 | getDisplayValue() {
|
14002 | if (this.valueFormatting) {
|
14003 | return this.valueFormatting(this.value);
|
14004 | }
|
14005 | return this.value.toLocaleString();
|
14006 | }
|
14007 | scaleText(element, repeat = true) {
|
14008 | let el;
|
14009 | let resizeScale;
|
14010 | if (element === ElementType.Value) {
|
14011 | el = this.valueTextEl;
|
14012 | resizeScale = this.valueResizeScale;
|
14013 | }
|
14014 | else {
|
14015 | el = this.unitsTextEl;
|
14016 | resizeScale = this.unitsResizeScale;
|
14017 | }
|
14018 | const { width, height } = el.nativeElement.getBoundingClientRect();
|
14019 | if (width === 0 || height === 0)
|
14020 | return;
|
14021 | const oldScale = resizeScale;
|
14022 | const availableWidth = this.dims.width;
|
14023 | const availableHeight = Math.max(this.dims.height / 2 - 15, 0);
|
14024 | const resizeScaleWidth = Math.floor((availableWidth / (width / resizeScale)) * 100) / 100;
|
14025 | const resizeScaleHeight = Math.floor((availableHeight / (height / resizeScale)) * 100) / 100;
|
14026 | resizeScale = Math.min(resizeScaleHeight, resizeScaleWidth);
|
14027 | if (resizeScale !== oldScale) {
|
14028 | if (element === ElementType.Value) {
|
14029 | this.valueResizeScale = resizeScale;
|
14030 | this.valueTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
14031 | }
|
14032 | else {
|
14033 | this.unitsResizeScale = resizeScale;
|
14034 | this.unitsTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
14035 | }
|
14036 | this.cd.markForCheck();
|
14037 | if (repeat && isPlatformBrowser(this.platformId)) {
|
14038 | setTimeout(() => {
|
14039 | this.scaleText(element, false);
|
14040 | }, 50);
|
14041 | }
|
14042 | }
|
14043 | }
|
14044 | scaleTextSSR(element) {
|
14045 | let resizeScale = 1;
|
14046 | const value = element === 'value' ? this.displayValue : this.units;
|
14047 | const width = calculateTextWidth(VERDANA_FONT_WIDTHS_16_PX, value, 10);
|
14048 | const height = 25;
|
14049 | const availableWidth = this.dims.width;
|
14050 | const availableHeight = Math.max(this.dims.height / 2 - 15, 0);
|
14051 | const resizeScaleWidth = Math.floor((availableWidth / (width / resizeScale)) * 100) / 100;
|
14052 | const resizeScaleHeight = Math.floor((availableHeight / (height / resizeScale)) * 100) / 100;
|
14053 | resizeScale = Math.min(resizeScaleHeight, resizeScaleWidth);
|
14054 | if (element === 'value') {
|
14055 | this.valueResizeScale = resizeScale;
|
14056 | this.valueTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
14057 | }
|
14058 | else {
|
14059 | this.unitsResizeScale = resizeScale;
|
14060 | this.unitsTextTransform = `scale(${resizeScale}, ${resizeScale})`;
|
14061 | }
|
14062 | this.cd.markForCheck();
|
14063 | }
|
14064 | onClick() {
|
14065 | this.select.emit({
|
14066 | name: 'Value',
|
14067 | value: this.value
|
14068 | });
|
14069 | }
|
14070 | setColors() {
|
14071 | this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, [this.value], this.customColors);
|
14072 | }
|
14073 | }
|
14074 | LinearGaugeComponent.decorators = [
|
14075 | { type: Component, args: [{
|
14076 | selector: 'ngx-charts-linear-gauge',
|
14077 | template: `
|
14078 | <ngx-charts-chart [view]="[width, height]" [showLegend]="false" [animations]="animations" (click)="onClick()">
|
14079 | <svg:g class="linear-gauge chart">
|
14080 | <svg:g
|
14081 | ngx-charts-bar
|
14082 | class="background-bar"
|
14083 | [width]="dims.width"
|
14084 | [height]="3"
|
14085 | [x]="margin[3]"
|
14086 | [y]="dims.height / 2 + margin[0] - 2"
|
14087 | [data]="{}"
|
14088 | [orientation]="barOrientation.Horizontal"
|
14089 | [roundEdges]="true"
|
14090 | [animations]="animations"
|
14091 | ></svg:g>
|
14092 | <svg:g
|
14093 | ngx-charts-bar
|
14094 | [width]="valueScale(value)"
|
14095 | [height]="3"
|
14096 | [x]="margin[3]"
|
14097 | [y]="dims.height / 2 + margin[0] - 2"
|
14098 | [fill]="colors.getColor(units)"
|
14099 | [data]="{}"
|
14100 | [orientation]="barOrientation.Horizontal"
|
14101 | [roundEdges]="true"
|
14102 | [animations]="animations"
|
14103 | ></svg:g>
|
14104 |
|
14105 | <svg:line
|
14106 | *ngIf="hasPreviousValue"
|
14107 | [attr.transform]="transformLine"
|
14108 | x1="0"
|
14109 | y1="5"
|
14110 | x2="0"
|
14111 | y2="15"
|
14112 | [attr.stroke]="colors.getColor(units)"
|
14113 | />
|
14114 |
|
14115 | <svg:line
|
14116 | *ngIf="hasPreviousValue"
|
14117 | [attr.transform]="transformLine"
|
14118 | x1="0"
|
14119 | y1="-5"
|
14120 | x2="0"
|
14121 | y2="-15"
|
14122 | [attr.stroke]="colors.getColor(units)"
|
14123 | />
|
14124 |
|
14125 | <svg:g [attr.transform]="transform">
|
14126 | <svg:g [attr.transform]="valueTranslate">
|
14127 | <svg:text
|
14128 | #valueTextEl
|
14129 | class="value"
|
14130 | [style.textAnchor]="'middle'"
|
14131 | [attr.transform]="valueTextTransform"
|
14132 | alignment-baseline="after-edge"
|
14133 | >
|
14134 | {{ displayValue }}
|
14135 | </svg:text>
|
14136 | </svg:g>
|
14137 |
|
14138 | <svg:g [attr.transform]="unitsTranslate">
|
14139 | <svg:text
|
14140 | #unitsTextEl
|
14141 | class="units"
|
14142 | [style.textAnchor]="'middle'"
|
14143 | [attr.transform]="unitsTextTransform"
|
14144 | alignment-baseline="before-edge"
|
14145 | >
|
14146 | {{ units }}
|
14147 | </svg:text>
|
14148 | </svg:g>
|
14149 | </svg:g>
|
14150 | </svg:g>
|
14151 | </ngx-charts-chart>
|
14152 | `,
|
14153 | encapsulation: ViewEncapsulation.None,
|
14154 | changeDetection: ChangeDetectionStrategy.OnPush,
|
14155 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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"]
|
14156 | },] }
|
14157 | ];
|
14158 | LinearGaugeComponent.propDecorators = {
|
14159 | min: [{ type: Input }],
|
14160 | max: [{ type: Input }],
|
14161 | value: [{ type: Input }],
|
14162 | units: [{ type: Input }],
|
14163 | previousValue: [{ type: Input }],
|
14164 | valueFormatting: [{ type: Input }],
|
14165 | valueTextEl: [{ type: ViewChild, args: ['valueTextEl',] }],
|
14166 | unitsTextEl: [{ type: ViewChild, args: ['unitsTextEl',] }]
|
14167 | };
|
14168 |
|
14169 | class GaugeComponent extends BaseChartComponent {
|
14170 | constructor() {
|
14171 | super(...arguments);
|
14172 | this.legend = false;
|
14173 | this.legendTitle = 'Legend';
|
14174 | this.legendPosition = LegendPosition.Right;
|
14175 | this.min = 0;
|
14176 | this.max = 100;
|
14177 | this.bigSegments = 10;
|
14178 | this.smallSegments = 5;
|
14179 | this.showAxis = true;
|
14180 | this.startAngle = -120;
|
14181 | this.angleSpan = 240;
|
14182 | this.activeEntries = [];
|
14183 | this.tooltipDisabled = false;
|
14184 | this.showText = true;
|
14185 | this.activate = new EventEmitter();
|
14186 | this.deactivate = new EventEmitter();
|
14187 | this.resizeScale = 1;
|
14188 | this.rotation = '';
|
14189 | this.textTransform = 'scale(1, 1)';
|
14190 | this.cornerRadius = 10;
|
14191 | }
|
14192 | ngAfterViewInit() {
|
14193 | super.ngAfterViewInit();
|
14194 | setTimeout(() => this.scaleText());
|
14195 | }
|
14196 | update() {
|
14197 | super.update();
|
14198 | if (!this.showAxis) {
|
14199 | if (!this.margin) {
|
14200 | this.margin = [10, 20, 10, 20];
|
14201 | }
|
14202 | }
|
14203 | else {
|
14204 | if (!this.margin) {
|
14205 | this.margin = [60, 100, 60, 100];
|
14206 | }
|
14207 | }
|
14208 |
|
14209 | if (this.startAngle < 0) {
|
14210 | this.startAngle = (this.startAngle % 360) + 360;
|
14211 | }
|
14212 | this.angleSpan = Math.min(this.angleSpan, 360);
|
14213 | this.dims = calculateViewDimensions({
|
14214 | width: this.width,
|
14215 | height: this.height,
|
14216 | margins: this.margin,
|
14217 | showLegend: this.legend,
|
14218 | legendPosition: this.legendPosition
|
14219 | });
|
14220 | this.domain = this.getDomain();
|
14221 | this.valueDomain = this.getValueDomain();
|
14222 | this.valueScale = this.getValueScale();
|
14223 | this.displayValue = this.getDisplayValue();
|
14224 | this.outerRadius = Math.min(this.dims.width, this.dims.height) / 2;
|
14225 | this.arcs = this.getArcs();
|
14226 | this.setColors();
|
14227 | this.legendOptions = this.getLegendOptions();
|
14228 | const xOffset = this.margin[3] + this.dims.width / 2;
|
14229 | const yOffset = this.margin[0] + this.dims.height / 2;
|
14230 | this.transform = `translate(${xOffset}, ${yOffset})`;
|
14231 | this.rotation = `rotate(${this.startAngle})`;
|
14232 | setTimeout(() => this.scaleText(), 50);
|
14233 | }
|
14234 | getArcs() {
|
14235 | const arcs = [];
|
14236 | const availableRadius = this.outerRadius * 0.7;
|
14237 | const radiusPerArc = Math.min(availableRadius / this.results.length, 10);
|
14238 | const arcWidth = radiusPerArc * 0.7;
|
14239 | this.textRadius = this.outerRadius - this.results.length * radiusPerArc;
|
14240 | this.cornerRadius = Math.floor(arcWidth / 2);
|
14241 | let i = 0;
|
14242 | for (const d of this.results) {
|
14243 | const outerRadius = this.outerRadius - i * radiusPerArc;
|
14244 | const innerRadius = outerRadius - arcWidth;
|
14245 | const backgroundArc = {
|
14246 | endAngle: (this.angleSpan * Math.PI) / 180,
|
14247 | innerRadius,
|
14248 | outerRadius,
|
14249 | data: {
|
14250 | value: this.max,
|
14251 | name: d.name
|
14252 | }
|
14253 | };
|
14254 | const valueArc = {
|
14255 | endAngle: (Math.min(this.valueScale(d.value), this.angleSpan) * Math.PI) / 180,
|
14256 | innerRadius,
|
14257 | outerRadius,
|
14258 | data: {
|
14259 | value: d.value,
|
14260 | name: d.name
|
14261 | }
|
14262 | };
|
14263 | const arc = {
|
14264 | backgroundArc,
|
14265 | valueArc
|
14266 | };
|
14267 | arcs.push(arc);
|
14268 | i++;
|
14269 | }
|
14270 | return arcs;
|
14271 | }
|
14272 | getDomain() {
|
14273 | return this.results.map(d => d.name);
|
14274 | }
|
14275 | getValueDomain() {
|
14276 | const values = this.results.map(d => d.value);
|
14277 | const dataMin = Math.min(...values);
|
14278 | const dataMax = Math.max(...values);
|
14279 | if (this.min !== undefined) {
|
14280 | this.min = Math.min(this.min, dataMin);
|
14281 | }
|
14282 | else {
|
14283 | this.min = dataMin;
|
14284 | }
|
14285 | if (this.max !== undefined) {
|
14286 | this.max = Math.max(this.max, dataMax);
|
14287 | }
|
14288 | else {
|
14289 | this.max = dataMax;
|
14290 | }
|
14291 | return [this.min, this.max];
|
14292 | }
|
14293 | getValueScale() {
|
14294 | return scaleLinear().range([0, this.angleSpan]).nice().domain(this.valueDomain);
|
14295 | }
|
14296 | getDisplayValue() {
|
14297 | const value = this.results.map(d => d.value).reduce((a, b) => a + b, 0);
|
14298 | if (this.textValue && 0 !== this.textValue.length) {
|
14299 | return this.textValue.toLocaleString();
|
14300 | }
|
14301 | if (this.valueFormatting) {
|
14302 | return this.valueFormatting(value);
|
14303 | }
|
14304 | return value.toLocaleString();
|
14305 | }
|
14306 | scaleText(repeat = true) {
|
14307 | if (!this.showText) {
|
14308 | return;
|
14309 | }
|
14310 | const { width } = this.textEl.nativeElement.getBoundingClientRect();
|
14311 | const oldScale = this.resizeScale;
|
14312 | if (width === 0) {
|
14313 | this.resizeScale = 1;
|
14314 | }
|
14315 | else {
|
14316 | const availableSpace = this.textRadius;
|
14317 | this.resizeScale = Math.floor((availableSpace / (width / this.resizeScale)) * 100) / 100;
|
14318 | }
|
14319 | if (this.resizeScale !== oldScale) {
|
14320 | this.textTransform = `scale(${this.resizeScale}, ${this.resizeScale})`;
|
14321 | this.cd.markForCheck();
|
14322 | if (repeat) {
|
14323 | setTimeout(() => this.scaleText(false), 50);
|
14324 | }
|
14325 | }
|
14326 | }
|
14327 | onClick(data) {
|
14328 | this.select.emit(data);
|
14329 | }
|
14330 | getLegendOptions() {
|
14331 | return {
|
14332 | scaleType: ScaleType.Ordinal,
|
14333 | colors: this.colors,
|
14334 | domain: this.domain,
|
14335 | title: this.legendTitle,
|
14336 | position: this.legendPosition
|
14337 | };
|
14338 | }
|
14339 | setColors() {
|
14340 | this.colors = new ColorHelper(this.scheme, ScaleType.Ordinal, this.domain, this.customColors);
|
14341 | }
|
14342 | onActivate(item) {
|
14343 | const idx = this.activeEntries.findIndex(d => {
|
14344 | return d.name === item.name && d.value === item.value;
|
14345 | });
|
14346 | if (idx > -1) {
|
14347 | return;
|
14348 | }
|
14349 | this.activeEntries = [item, ...this.activeEntries];
|
14350 | this.activate.emit({ value: item, entries: this.activeEntries });
|
14351 | }
|
14352 | onDeactivate(item) {
|
14353 | const idx = this.activeEntries.findIndex(d => {
|
14354 | return d.name === item.name && d.value === item.value;
|
14355 | });
|
14356 | this.activeEntries.splice(idx, 1);
|
14357 | this.activeEntries = [...this.activeEntries];
|
14358 | this.deactivate.emit({ value: item, entries: this.activeEntries });
|
14359 | }
|
14360 | isActive(entry) {
|
14361 | if (!this.activeEntries)
|
14362 | return false;
|
14363 | const item = this.activeEntries.find(d => {
|
14364 | return entry.name === d.name && entry.series === d.series;
|
14365 | });
|
14366 | return item !== undefined;
|
14367 | }
|
14368 | trackBy(index, item) {
|
14369 | return item.valueArc.data.name;
|
14370 | }
|
14371 | }
|
14372 | GaugeComponent.decorators = [
|
14373 | { type: Component, args: [{
|
14374 | selector: 'ngx-charts-gauge',
|
14375 | template: `
|
14376 | <ngx-charts-chart
|
14377 | [view]="[width, height]"
|
14378 | [showLegend]="legend"
|
14379 | [legendOptions]="legendOptions"
|
14380 | [activeEntries]="activeEntries"
|
14381 | [animations]="animations"
|
14382 | (legendLabelClick)="onClick($event)"
|
14383 | (legendLabelActivate)="onActivate($event)"
|
14384 | (legendLabelDeactivate)="onDeactivate($event)"
|
14385 | >
|
14386 | <svg:g [attr.transform]="transform" class="gauge chart">
|
14387 | <svg:g *ngFor="let arc of arcs; trackBy: trackBy" [attr.transform]="rotation">
|
14388 | <svg:g
|
14389 | ngx-charts-gauge-arc
|
14390 | [backgroundArc]="arc.backgroundArc"
|
14391 | [valueArc]="arc.valueArc"
|
14392 | [cornerRadius]="cornerRadius"
|
14393 | [colors]="colors"
|
14394 | [isActive]="isActive(arc.valueArc.data)"
|
14395 | [tooltipDisabled]="tooltipDisabled"
|
14396 | [tooltipTemplate]="tooltipTemplate"
|
14397 | [valueFormatting]="valueFormatting"
|
14398 | [animations]="animations"
|
14399 | (select)="onClick($event)"
|
14400 | (activate)="onActivate($event)"
|
14401 | (deactivate)="onDeactivate($event)"
|
14402 | ></svg:g>
|
14403 | </svg:g>
|
14404 |
|
14405 | <svg:g
|
14406 | ngx-charts-gauge-axis
|
14407 | *ngIf="showAxis"
|
14408 | [bigSegments]="bigSegments"
|
14409 | [smallSegments]="smallSegments"
|
14410 | [min]="min"
|
14411 | [max]="max"
|
14412 | [radius]="outerRadius"
|
14413 | [angleSpan]="angleSpan"
|
14414 | [valueScale]="valueScale"
|
14415 | [startAngle]="startAngle"
|
14416 | [tickFormatting]="axisTickFormatting"
|
14417 | ></svg:g>
|
14418 |
|
14419 | <svg:text
|
14420 | #textEl
|
14421 | *ngIf="showText"
|
14422 | [style.textAnchor]="'middle'"
|
14423 | [attr.transform]="textTransform"
|
14424 | alignment-baseline="central"
|
14425 | >
|
14426 | <tspan x="0" dy="0">{{ displayValue }}</tspan>
|
14427 | <tspan x="0" dy="1.2em">{{ units }}</tspan>
|
14428 | </svg:text>
|
14429 | </svg:g>
|
14430 | </ngx-charts-chart>
|
14431 | `,
|
14432 | encapsulation: ViewEncapsulation.None,
|
14433 | changeDetection: ChangeDetectionStrategy.OnPush,
|
14434 | styles: [".ngx-charts{float:left;overflow:visible}.ngx-charts .circle,.ngx-charts .cell,.ngx-charts .bar,.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 .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 .card:focus{outline:none}.ngx-charts .bar.hidden,.ngx-charts .cell.hidden,.ngx-charts .arc.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:normal}.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:bold}.gauge .gauge-tick-large path{stroke-width:2px}.gauge .gauge-tick-small path{stroke-width:1px}\n"]
|
14435 | },] }
|
14436 | ];
|
14437 | GaugeComponent.propDecorators = {
|
14438 | legend: [{ type: Input }],
|
14439 | legendTitle: [{ type: Input }],
|
14440 | legendPosition: [{ type: Input }],
|
14441 | min: [{ type: Input }],
|
14442 | max: [{ type: Input }],
|
14443 | textValue: [{ type: Input }],
|
14444 | units: [{ type: Input }],
|
14445 | bigSegments: [{ type: Input }],
|
14446 | smallSegments: [{ type: Input }],
|
14447 | results: [{ type: Input }],
|
14448 | showAxis: [{ type: Input }],
|
14449 | startAngle: [{ type: Input }],
|
14450 | angleSpan: [{ type: Input }],
|
14451 | activeEntries: [{ type: Input }],
|
14452 | axisTickFormatting: [{ type: Input }],
|
14453 | tooltipDisabled: [{ type: Input }],
|
14454 | valueFormatting: [{ type: Input }],
|
14455 | showText: [{ type: Input }],
|
14456 | margin: [{ type: Input }],
|
14457 | activate: [{ type: Output }],
|
14458 | deactivate: [{ type: Output }],
|
14459 | tooltipTemplate: [{ type: ContentChild, args: ['tooltipTemplate',] }],
|
14460 | textEl: [{ type: ViewChild, args: ['textEl',] }]
|
14461 | };
|
14462 |
|
14463 | class GaugeArcComponent {
|
14464 | constructor() {
|
14465 | this.isActive = false;
|
14466 | this.tooltipDisabled = false;
|
14467 | this.animations = true;
|
14468 | this.select = new EventEmitter();
|
14469 | this.activate = new EventEmitter();
|
14470 | this.deactivate = new EventEmitter();
|
14471 | this.placementTypes = PlacementTypes;
|
14472 | this.styleTypes = StyleTypes;
|
14473 | }
|
14474 | tooltipText(arc) {
|
14475 | const label = formatLabel(arc.data.name);
|
14476 | let val;
|
14477 | if (this.valueFormatting) {
|
14478 | val = this.valueFormatting(arc.data.value);
|
14479 | }
|
14480 | else {
|
14481 | val = formatLabel(arc.data.value);
|
14482 | }
|
14483 | return `
|
14484 | <span class="tooltip-label">${escapeLabel(label)}</span>
|
14485 | <span class="tooltip-val">${val}</span>
|
14486 | `;
|
14487 | }
|
14488 | }
|
14489 | GaugeArcComponent.decorators = [
|
14490 | { type: Component, args: [{
|
14491 | selector: 'g[ngx-charts-gauge-arc]',
|
14492 | template: `
|
14493 | <svg:g
|
14494 | ngx-charts-pie-arc
|
14495 | class="background-arc"
|
14496 | [startAngle]="0"
|
14497 | [endAngle]="backgroundArc.endAngle"
|
14498 | [innerRadius]="backgroundArc.innerRadius"
|
14499 | [outerRadius]="backgroundArc.outerRadius"
|
14500 | [cornerRadius]="cornerRadius"
|
14501 | [data]="backgroundArc.data"
|
14502 | [animate]="false"
|
14503 | [pointerEvents]="false"
|
14504 | ></svg:g>
|
14505 | <svg:g
|
14506 | ngx-charts-pie-arc
|
14507 | [startAngle]="0"
|
14508 | [endAngle]="valueArc.endAngle"
|
14509 | [innerRadius]="valueArc.innerRadius"
|
14510 | [outerRadius]="valueArc.outerRadius"
|
14511 | [cornerRadius]="cornerRadius"
|
14512 | [fill]="colors.getColor(valueArc.data.name)"
|
14513 | [data]="valueArc.data"
|
14514 | [animate]="animations"
|
14515 | [isActive]="isActive"
|
14516 | (select)="select.emit($event)"
|
14517 | (activate)="activate.emit($event)"
|
14518 | (deactivate)="deactivate.emit($event)"
|
14519 | ngx-tooltip
|
14520 | [tooltipDisabled]="tooltipDisabled"
|
14521 | [tooltipPlacement]="placementTypes.Top"
|
14522 | [tooltipType]="styleTypes.tooltip"
|
14523 | [tooltipTitle]="tooltipTemplate ? undefined : tooltipText(valueArc)"
|
14524 | [tooltipTemplate]="tooltipTemplate"
|
14525 | [tooltipContext]="valueArc.data"
|
14526 | ></svg:g>
|
14527 | `,
|
14528 | changeDetection: ChangeDetectionStrategy.OnPush
|
14529 | },] }
|
14530 | ];
|
14531 | GaugeArcComponent.propDecorators = {
|
14532 | backgroundArc: [{ type: Input }],
|
14533 | valueArc: [{ type: Input }],
|
14534 | cornerRadius: [{ type: Input }],
|
14535 | colors: [{ type: Input }],
|
14536 | isActive: [{ type: Input }],
|
14537 | tooltipDisabled: [{ type: Input }],
|
14538 | valueFormatting: [{ type: Input }],
|
14539 | tooltipTemplate: [{ type: Input }],
|
14540 | animations: [{ type: Input }],
|
14541 | select: [{ type: Output }],
|
14542 | activate: [{ type: Output }],
|
14543 | deactivate: [{ type: Output }]
|
14544 | };
|
14545 |
|
14546 | class GaugeAxisComponent {
|
14547 | constructor() {
|
14548 | this.rotate = '';
|
14549 | }
|
14550 | ngOnChanges(changes) {
|
14551 | this.update();
|
14552 | }
|
14553 | update() {
|
14554 | this.rotationAngle = -90 + this.startAngle;
|
14555 | this.rotate = `rotate(${this.rotationAngle})`;
|
14556 | this.ticks = this.getTicks();
|
14557 | }
|
14558 | getTicks() {
|
14559 | const bigTickSegment = this.angleSpan / this.bigSegments;
|
14560 | const smallTickSegment = bigTickSegment / this.smallSegments;
|
14561 | const tickLength = 20;
|
14562 | const ticks = {
|
14563 | big: [],
|
14564 | small: []
|
14565 | };
|
14566 | const startDistance = this.radius + 10;
|
14567 | const textDist = startDistance + tickLength + 10;
|
14568 | for (let i = 0; i <= this.bigSegments; i++) {
|
14569 | const angleDeg = i * bigTickSegment;
|
14570 | const angle = (angleDeg * Math.PI) / 180;
|
14571 | const textAnchor = this.getTextAnchor(angleDeg);
|
14572 | let skip = false;
|
14573 | if (i === 0 && this.angleSpan === 360) {
|
14574 | skip = true;
|
14575 | }
|
14576 | if (!skip) {
|
14577 | let text = Number.parseFloat(this.valueScale.invert(angleDeg).toString()).toLocaleString();
|
14578 | if (this.tickFormatting) {
|
14579 | text = this.tickFormatting(text);
|
14580 | }
|
14581 | ticks.big.push({
|
14582 | line: this.getTickPath(startDistance, tickLength, angle),
|
14583 | textAnchor,
|
14584 | text,
|
14585 | textTransform: `
|
14586 | translate(${textDist * Math.cos(angle)}, ${textDist * Math.sin(angle)}) rotate(${-this.rotationAngle})
|
14587 | `
|
14588 | });
|
14589 | }
|
14590 | if (i === this.bigSegments) {
|
14591 | continue;
|
14592 | }
|
14593 | for (let j = 1; j <= this.smallSegments; j++) {
|
14594 | const smallAngleDeg = angleDeg + j * smallTickSegment;
|
14595 | const smallAngle = (smallAngleDeg * Math.PI) / 180;
|
14596 | ticks.small.push({
|
14597 | line: this.getTickPath(startDistance, tickLength / 2, smallAngle)
|
14598 | });
|
14599 | }
|
14600 | }
|
14601 | return ticks;
|
14602 | }
|
14603 | getTextAnchor(angle) {
|
14604 |
|
14605 |
|
14606 |
|
14607 |
|
14608 | angle = (this.startAngle + angle) % 360;
|
14609 | let textAnchor = TextAnchor.Middle;
|
14610 | if (angle > 45 && angle <= 135) {
|
14611 | textAnchor = TextAnchor.Start;
|
14612 | }
|
14613 | else if (angle > 225 && angle <= 315) {
|
14614 | textAnchor = TextAnchor.End;
|
14615 | }
|
14616 | return textAnchor;
|
14617 | }
|
14618 | getTickPath(startDistance, tickLength, angle) {
|
14619 | const y1 = startDistance * Math.sin(angle);
|
14620 | const y2 = (startDistance + tickLength) * Math.sin(angle);
|
14621 | const x1 = startDistance * Math.cos(angle);
|
14622 | const x2 = (startDistance + tickLength) * Math.cos(angle);
|
14623 | const points = [
|
14624 | { x: x1, y: y1 },
|
14625 | { x: x2, y: y2 }
|
14626 | ];
|
14627 | const lineGenerator = line()
|
14628 | .x(d => d.x)
|
14629 | .y(d => d.y);
|
14630 | return lineGenerator(points);
|
14631 | }
|
14632 | }
|
14633 | GaugeAxisComponent.decorators = [
|
14634 | { type: Component, args: [{
|
14635 | selector: 'g[ngx-charts-gauge-axis]',
|
14636 | template: `
|
14637 | <svg:g [attr.transform]="rotate">
|
14638 | <svg:g *ngFor="let tick of ticks.big" class="gauge-tick gauge-tick-large">
|
14639 | <svg:path [attr.d]="tick.line" />
|
14640 | </svg:g>
|
14641 | <svg:g *ngFor="let tick of ticks.big" class="gauge-tick gauge-tick-large">
|
14642 | <svg:text
|
14643 | [style.textAnchor]="tick.textAnchor"
|
14644 | [attr.transform]="tick.textTransform"
|
14645 | alignment-baseline="central"
|
14646 | >
|
14647 | {{ tick.text }}
|
14648 | </svg:text>
|
14649 | </svg:g>
|
14650 | <svg:g *ngFor="let tick of ticks.small" class="gauge-tick gauge-tick-small">
|
14651 | <svg:path [attr.d]="tick.line" />
|
14652 | </svg:g>
|
14653 | </svg:g>
|
14654 | `,
|
14655 | changeDetection: ChangeDetectionStrategy.OnPush
|
14656 | },] }
|
14657 | ];
|
14658 | GaugeAxisComponent.propDecorators = {
|
14659 | bigSegments: [{ type: Input }],
|
14660 | smallSegments: [{ type: Input }],
|
14661 | min: [{ type: Input }],
|
14662 | max: [{ type: Input }],
|
14663 | angleSpan: [{ type: Input }],
|
14664 | startAngle: [{ type: Input }],
|
14665 | radius: [{ type: Input }],
|
14666 | valueScale: [{ type: Input }],
|
14667 | tickFormatting: [{ type: Input }]
|
14668 | };
|
14669 |
|
14670 | class GaugeModule {
|
14671 | }
|
14672 | GaugeModule.decorators = [
|
14673 | { type: NgModule, args: [{
|
14674 | imports: [ChartCommonModule, PieChartModule, BarChartModule],
|
14675 | declarations: [LinearGaugeComponent, GaugeComponent, GaugeArcComponent, GaugeAxisComponent],
|
14676 | exports: [LinearGaugeComponent, GaugeComponent, GaugeArcComponent, GaugeAxisComponent]
|
14677 | },] }
|
14678 | ];
|
14679 |
|
14680 |
|
14681 | function ngxChartsPolyfills() {
|
14682 |
|
14683 |
|
14684 | if (typeof SVGElement !== 'undefined' && typeof SVGElement.prototype.contains === 'undefined') {
|
14685 | SVGElement.prototype.contains = HTMLDivElement.prototype.contains;
|
14686 | }
|
14687 | }
|
14688 |
|
14689 | class NgxChartsModule {
|
14690 | constructor() {
|
14691 | ngxChartsPolyfills();
|
14692 | }
|
14693 | }
|
14694 | NgxChartsModule.decorators = [
|
14695 | { type: NgModule, args: [{
|
14696 | exports: [
|
14697 | ChartCommonModule,
|
14698 | AreaChartModule,
|
14699 | BarChartModule,
|
14700 | BoxChartModule,
|
14701 | BubbleChartModule,
|
14702 | HeatMapModule,
|
14703 | LineChartModule,
|
14704 | PolarChartModule,
|
14705 | NumberCardModule,
|
14706 | PieChartModule,
|
14707 | TreeMapModule,
|
14708 | GaugeModule
|
14709 | ]
|
14710 | },] }
|
14711 | ];
|
14712 | NgxChartsModule.ctorParameters = () => [];
|
14713 |
|
14714 | function tickFormat(fieldType, groupByType) {
|
14715 | return function (label) {
|
14716 | if (label === 'No Value' || label === 'Other') {
|
14717 | return label;
|
14718 | }
|
14719 | if (fieldType === 'date' && groupByType === 'groupBy') {
|
14720 | const formatter = timeFormat('MM/DD/YYYY');
|
14721 | return formatter(label);
|
14722 | }
|
14723 | return label.toString();
|
14724 | };
|
14725 | }
|
14726 |
|
14727 |
|
14728 |
|
14729 |
|
14730 |
|
14731 |
|
14732 |
|
14733 |
|
14734 |
|
14735 | 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, 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, getUniqueXDomainValues, getXDomainArray, gridLayout, gridSize, hexToRgb, id, invertColor, reduceTicks, shadeRGBColor, sortByDomain, sortByTime, sortLinear, throttle, throttleable, tickFormat, trimLabel, InjectionRegisteryService as ɵa, InjectionService as ɵb };
|
14736 |
|