|
|
@@ -0,0 +1,184 @@
|
|
|
+import {AfterViewInit, Component, Input, OnInit} from '@angular/core';
|
|
|
+
|
|
|
+import {select} from 'd3';
|
|
|
+
|
|
|
+import {SdmDihService} from '../sdm-dih.service';
|
|
|
+import {YearGraphService} from './year-graph.service';
|
|
|
+
|
|
|
+@Component({
|
|
|
+ // eslint-disable-next-line @angular-eslint/component-selector
|
|
|
+ selector: 'disc',
|
|
|
+ templateUrl: 'disc.component.html',
|
|
|
+})
|
|
|
+export class DiscComponent implements OnInit, AfterViewInit {
|
|
|
+ @Input() domain = 'baseline'; //TODO: useless? scenario is unique and contains domain per se
|
|
|
+ @Input() factor = 'aggregated';
|
|
|
+ @Input() region: string;
|
|
|
+ @Input() scenario = 'baseline';
|
|
|
+ @Input() show: 'name' | 'factor' = 'name';
|
|
|
+ divId = 'graph-place';
|
|
|
+ private arrowUse;
|
|
|
+ private regionData;
|
|
|
+ private svgContent;
|
|
|
+ private svgContentText;
|
|
|
+
|
|
|
+ constructor(
|
|
|
+ public sdmDihService: SdmDihService,
|
|
|
+ public yearGraphService: YearGraphService
|
|
|
+ ) {}
|
|
|
+
|
|
|
+ ngOnInit(): void {
|
|
|
+ const regionSafeName = this.region.replace(' ', '_');
|
|
|
+ const scenarioSafeName = this.scenario.replace(' ', '_');
|
|
|
+ const factorSafeName = this.factor.split('/').slice(-1).pop();
|
|
|
+ const nonce = Math.round(Math.random() * 10000) + '';
|
|
|
+ this.divId = `graph-place-${regionSafeName}-${scenarioSafeName}-${factorSafeName}-${nonce}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ ngAfterViewInit(): void {
|
|
|
+ this.sdmDihService.dataLoads.subscribe((loaded) => {
|
|
|
+ if (!loaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.drawGraph();
|
|
|
+ });
|
|
|
+ this.yearGraphService.graphRefreshes.subscribe(() => {
|
|
|
+ this.updateGraph();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ drawGraph(): void {
|
|
|
+ const year = this.yearGraphService.selectedYear.toString().includes('.')
|
|
|
+ ? this.yearGraphService.selectedYear
|
|
|
+ : this.yearGraphService.selectedYear + '.0';
|
|
|
+ this.regionData = this.sdmDihService.sdmData[year].find(
|
|
|
+ (row) => row['MODEL'] === this.region && row['SCENARIO'] === this.scenario
|
|
|
+ );
|
|
|
+ /* When the parent element has position "flex", this can be set to 100% */
|
|
|
+ const width = 100; // / this.sdmDihService.regions.length;
|
|
|
+ const height = 100; // / this.sdmDihService.regions.length;
|
|
|
+ /* append the svg object to the div called 'graph-place-...' */
|
|
|
+ const svg = select(`#${this.divId}`)
|
|
|
+ .append('svg')
|
|
|
+ .attr('width', `${width}%`)
|
|
|
+ .attr('height', `${height}%`)
|
|
|
+ .append('svg')
|
|
|
+ .attr('x', '50%')
|
|
|
+ .attr('y', '50%')
|
|
|
+ .attr('overflow', 'visible');
|
|
|
+ // arrow symbol for later re-use
|
|
|
+ const arrow = svg.append('symbol').attr('id', 'arrow');
|
|
|
+ // horizontal line
|
|
|
+ arrow
|
|
|
+ .append('line')
|
|
|
+ .attr('x1', 0)
|
|
|
+ .attr('y1', 30)
|
|
|
+ .attr('x2', 60)
|
|
|
+ .attr('y2', 30)
|
|
|
+ .attr('stroke', 'black')
|
|
|
+ .style('stroke-width', 4);
|
|
|
+ // upper line
|
|
|
+ arrow
|
|
|
+ .append('line')
|
|
|
+ .attr('x1', 40)
|
|
|
+ .attr('y1', 10)
|
|
|
+ .attr('x2', 60)
|
|
|
+ .attr('y2', 30)
|
|
|
+ .attr('stroke', 'black')
|
|
|
+ .style('stroke-width', 4);
|
|
|
+ // bottom line
|
|
|
+ arrow
|
|
|
+ .append('line')
|
|
|
+ .attr('x1', 40)
|
|
|
+ .attr('y1', 50)
|
|
|
+ .attr('x2', 60)
|
|
|
+ .attr('y2', 30)
|
|
|
+ .attr('stroke', 'black')
|
|
|
+ .style('stroke-width', 4);
|
|
|
+ this.svgContent = svg.append('g');
|
|
|
+ this.svgContent.data(() => [this.regionData]);
|
|
|
+ //.attr('transform', 'translate(' + width / 2 + '% ,' + height / 2 + '% )');
|
|
|
+ this.svgContent
|
|
|
+ .append('circle')
|
|
|
+ .attr('cx', 0)
|
|
|
+ .attr('cy', 0)
|
|
|
+ .attr('r', 50)
|
|
|
+ .attr('stroke', 'black')
|
|
|
+ .attr('fill', (d) => {
|
|
|
+ return this.sdmDihService.perc2color(
|
|
|
+ d[this.factor]?.index ?? d[this.factor]
|
|
|
+ );
|
|
|
+ });
|
|
|
+ this.svgContent
|
|
|
+ .append('text')
|
|
|
+ .attr('x', 0)
|
|
|
+ .attr('y', -60)
|
|
|
+ .attr('dy', '.35em')
|
|
|
+ .text((d) =>
|
|
|
+ this.show == 'name'
|
|
|
+ ? d['MODEL']
|
|
|
+ : this.factor.split('/').slice(-1).pop()
|
|
|
+ )
|
|
|
+ .style('text-anchor', 'middle');
|
|
|
+ this.svgContentText = this.svgContent.append('text');
|
|
|
+ this.svgContentText
|
|
|
+ .attr('x', 0)
|
|
|
+ .attr('y', 60)
|
|
|
+ .attr('dy', '.35em')
|
|
|
+ .text(
|
|
|
+ (d) =>
|
|
|
+ `${(
|
|
|
+ Number.parseFloat(d[this.factor]?.index ?? d[this.factor]) * 100
|
|
|
+ ).toFixed(2)} %`
|
|
|
+ )
|
|
|
+ .style('text-anchor', 'middle');
|
|
|
+ this.arrowUse = this.svgContent
|
|
|
+ .append('use')
|
|
|
+ .attr('xlink:href', '#arrow')
|
|
|
+ .attr('x', -30)
|
|
|
+ .attr('y', -30)
|
|
|
+ .attr(
|
|
|
+ 'transform',
|
|
|
+ // rotation is defined clockwise, hence -45 deg will turn the arrow up
|
|
|
+ (d) =>
|
|
|
+ `rotate(${
|
|
|
+ -45 *
|
|
|
+ this.yearGraphService.getRegionProgress(d, {factor: this.factor})
|
|
|
+ }, 0, 0)`
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ updateGraph(): void {
|
|
|
+ const year = this.yearGraphService.selectedYear.toString().includes('.')
|
|
|
+ ? this.yearGraphService.selectedYear
|
|
|
+ : this.yearGraphService.selectedYear + '.0';
|
|
|
+ this.regionData = this.sdmDihService.sdmData[year].find(
|
|
|
+ (row) => row['MODEL'] === this.region && row['SCENARIO'] === this.scenario
|
|
|
+ );
|
|
|
+ this.svgContent
|
|
|
+ .data(() => [this.regionData])
|
|
|
+ .select('circle')
|
|
|
+ .attr('fill', (d) => {
|
|
|
+ return this.sdmDihService.perc2color(
|
|
|
+ d[this.factor]?.index ?? d[this.factor]
|
|
|
+ );
|
|
|
+ });
|
|
|
+ this.svgContentText
|
|
|
+ .data([this.regionData])
|
|
|
+ .text(
|
|
|
+ (d) =>
|
|
|
+ `${(
|
|
|
+ Number.parseFloat(d[this.factor]?.index ?? d[this.factor]) * 100
|
|
|
+ ).toFixed(2)} %`
|
|
|
+ );
|
|
|
+ this.arrowUse.data([this.regionData]).attr(
|
|
|
+ 'transform',
|
|
|
+ // rotation is defined clockwise, hence -45 deg will turn the arrow up
|
|
|
+ (d) =>
|
|
|
+ `rotate(${
|
|
|
+ -45 *
|
|
|
+ this.yearGraphService.getRegionProgress(d, {factor: this.factor})
|
|
|
+ }, 0, 0)`
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|