- add "moment": "^2.29.1" and "chartjs-adapter-moment": "^1.0.0",
- add core module for time.service.ts - add interfaces for timespan.ts an dataset.ts
This commit is contained in:
parent
5f657dc9e4
commit
4241bd2cb9
15 changed files with 706 additions and 57 deletions
|
@ -1,61 +1,285 @@
|
|||
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Input, Component, AfterViewInit, ViewChild, ElementRef, SimpleChanges } from '@angular/core';
|
||||
// import * as d3 from 'd3';
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
import { Chart, LogarithmicScale, registerables } from 'chart.js';
|
||||
|
||||
import { GeomonTimeseries, DataConst, GeomonTimeseriesData } from '../../../shared/models/dataset';
|
||||
import { DatasetApiService } from '../../../app/services/dataset-api.service';
|
||||
import { DatasetService } from '../../../app/services/dataset.service';
|
||||
|
||||
import { Timespan } from '../../../shared/models/timespan';
|
||||
import { TimeService } from '../../core/time/time.service';
|
||||
import moment from 'moment';
|
||||
// import 'moment-duration-format';
|
||||
import { TimeValueTuple, Data } from '../../../shared/models/dataset';
|
||||
import 'chartjs-adapter-moment';
|
||||
import { MAT_SELECTION_LIST_VALUE_ACCESSOR } from '@angular/material/list';
|
||||
|
||||
@Component({
|
||||
selector: 'geomon-timeseries-chart',
|
||||
templateUrl: './geomon-timeseries-chart.component.html',
|
||||
styleUrls: ['./geomon-timeseries-chart.component.scss']
|
||||
})
|
||||
export class GeomonTimeseriesChartComponent implements OnInit {
|
||||
export class GeomonTimeseriesChartComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild('geomon_timeseries', { static: true })
|
||||
public d3Elem: ElementRef;
|
||||
// @ViewChild('geomon_timeseries', { static: true })
|
||||
// public chartElem: ElementRef;
|
||||
|
||||
|
||||
@ViewChild('geomon_timeseries') public chartElem: ElementRef;
|
||||
|
||||
lineChart: Chart;
|
||||
/**
|
||||
* The corresponding dataset options.
|
||||
*/
|
||||
@Input()
|
||||
public datasetOptions: Map<string, GeomonTimeseries>;
|
||||
|
||||
/**
|
||||
* List of presented dataset ids.
|
||||
*/
|
||||
@Input()
|
||||
public datasetIds: string[] = [];
|
||||
|
||||
|
||||
/**
|
||||
* The time interval in which the data should presented.
|
||||
*/
|
||||
@Input()
|
||||
public timeInterval: Timespan;
|
||||
|
||||
protected timespan: Timespan;
|
||||
|
||||
// data types
|
||||
protected datasetMap: Map<string, DataConst> = new Map();
|
||||
protected listOfUoms: string[] = [];
|
||||
|
||||
// private loadingData: Set<string> = new Set();
|
||||
|
||||
private width: number;
|
||||
private canvas: HTMLCanvasElement;
|
||||
private margin = {
|
||||
top: 10,
|
||||
right: 10,
|
||||
bottom: 40,
|
||||
left: 10
|
||||
};
|
||||
|
||||
constructor(
|
||||
protected datasetApiService: DatasetApiService,
|
||||
protected timeService: TimeService,
|
||||
public datasetService: DatasetService<GeomonTimeseries>,
|
||||
) { }
|
||||
|
||||
ngAfterViewInit(): void { // this.createSvg();
|
||||
|
||||
this.canvas = document.getElementById("line-chart") as HTMLCanvasElement;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
// this.createSvg();
|
||||
// this.drawBars(this.data);
|
||||
Chart.register(...registerables);
|
||||
this.drawBars();
|
||||
this.initChart();
|
||||
|
||||
for (let i = 0; i < this.datasetIds.length; i++) {
|
||||
let datasetId = this.datasetIds[i];
|
||||
let dataset = this.datasetOptions.get(datasetId);
|
||||
this.addDataset(dataset.id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/');
|
||||
}
|
||||
|
||||
// let firstDatasetId = this.datasetIds[0];
|
||||
// let dataset = this.datasetOptions.get(firstDatasetId);
|
||||
// this.addDataset(dataset.id, 'https://geomon.geologie.ac.at/52n-sos-webapp/api/');
|
||||
|
||||
|
||||
}
|
||||
|
||||
private drawBars(): void {
|
||||
let lineChart = document.getElementById("line-chart") as HTMLCanvasElement;
|
||||
new Chart(lineChart, {
|
||||
public ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.timeInterval && this.timeInterval) {
|
||||
this.timespan = this.timeService.createTimespanOfInterval(this.timeInterval);
|
||||
// this.timeIntervalChanges();
|
||||
}
|
||||
// if (changes.reloadForDatasets && this.reloadForDatasets && this.reloadDataForDatasets.length > 0) {
|
||||
// this.reloadDataForDatasets(this.reloadForDatasets);
|
||||
// }
|
||||
}
|
||||
|
||||
public getDataset(internalId: string) {
|
||||
return this.datasetMap.get(internalId);
|
||||
}
|
||||
|
||||
protected addDataset(id: string, url: string): void {
|
||||
// this.servicesConnector.getDataset({ id, url }, { locale: this.translateService.currentLang, type: DatasetType.Timeseries }).subscribe(
|
||||
// res => this.loadAddedDataset(res),
|
||||
// error => this.errorHandler.handleDatasetLoadError(error)
|
||||
// );
|
||||
this.datasetApiService.getDataset(id, url).subscribe({
|
||||
next: (res: GeomonTimeseries) => this.loadAddedDataset(res),
|
||||
error: (err: any) => console.error('Observer got an error: ' + err),
|
||||
complete: () => console.log('HTTP request completed.')
|
||||
// error => this.errorHandler.handleDatasetLoadError(error)
|
||||
});
|
||||
}
|
||||
|
||||
private loadAddedDataset(dataset: GeomonTimeseries): void {
|
||||
this.datasetMap.set(dataset.internalId, dataset);
|
||||
this.loadDatasetData(dataset, false);
|
||||
}
|
||||
|
||||
// load data of dataset
|
||||
private loadDatasetData(dataset: GeomonTimeseries, fprce: boolean): void {
|
||||
// const datasetOptions = this.datasetOptions.get(dataset.internalId);
|
||||
|
||||
// https://github.com/52North/helgoland-toolbox/blob/9ff9a42b34cd3deb181d56d76d48eba7c101554e/libs/core/src/lib/api-communication/connectors/dataset-api-v3-connector/dataset-api-v3-connector.ts#L270
|
||||
|
||||
const buffer = this.timeService.getBufferedTimespan(this.timespan, 5, moment.duration(1, 'day').asMilliseconds());
|
||||
|
||||
this.datasetApiService.getDatasetData(dataset, buffer, {})
|
||||
.subscribe({
|
||||
next: (result: GeomonTimeseriesData) => {
|
||||
this.prepareData(dataset, result);
|
||||
// this.onCompleteLoadingData(dataset);
|
||||
let test = result;
|
||||
},
|
||||
error: (error) => {
|
||||
// this.errorHandler.handleDataLoadError(error, dataset);
|
||||
// this.onCompleteLoadingData(dataset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to prepare each dataset for the graph and adding it to an array of datasets.
|
||||
* @param dataset {IDataset} Object of the whole dataset
|
||||
*/
|
||||
private prepareData(dataset: GeomonTimeseries, rawdata: GeomonTimeseriesData): void {
|
||||
|
||||
if (rawdata instanceof GeomonTimeseriesData) {
|
||||
// add surrounding entries to the set
|
||||
if (rawdata.valueBeforeTimespan) { rawdata.values.unshift(rawdata.valueBeforeTimespan); }
|
||||
if (rawdata.valueAfterTimespan) { rawdata.values.push(rawdata.valueAfterTimespan); }
|
||||
|
||||
const data = this.generalizeData(rawdata, this.width, this.timespan);
|
||||
|
||||
// this.datasetMap.get(dataset.internalId).data = data;
|
||||
this.addData(this.lineChart, dataset, rawdata);
|
||||
}
|
||||
}
|
||||
|
||||
public generalizeData(data: GeomonTimeseriesData, imageWidth: number, timespan: Timespan): Data<TimeValueTuple> {
|
||||
if (data.values.length > imageWidth && data.values.length > 0) {
|
||||
const duration = timespan.to - timespan.from;
|
||||
const dataduration = data.values[data.values.length - 1][0] - data.values[0][0];
|
||||
const factor = duration / dataduration;
|
||||
const realWidth = imageWidth / factor;
|
||||
const modulo = 1 / (data.values.length / realWidth);
|
||||
const generalizedData = {
|
||||
values: data.values.filter((v, i) => i % Math.round(modulo) === 0),
|
||||
referenceValues: data.referenceValues
|
||||
};
|
||||
console.log(`reduce from ${data.values.length} to ${generalizedData.values.length}`);
|
||||
return generalizedData;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private addData(chart: Chart, dataset: GeomonTimeseries, data: GeomonTimeseriesData): void {
|
||||
|
||||
let labels = data.values.map(function (label) {
|
||||
let date = moment(label[0]).format("YYYY-MM-DD HH:mm");
|
||||
return date;
|
||||
});
|
||||
|
||||
let values = data.values.map(function (value) {
|
||||
return value[1];
|
||||
});
|
||||
|
||||
chart.data.labels = labels;
|
||||
// chart.data.datasets.forEach((dataset) => {
|
||||
// dataset.data.push(data);
|
||||
// });
|
||||
let letters = '0123456789ABCDEF'.split('');
|
||||
let color = '#';
|
||||
for (let i = 0; i < 6; i++) {
|
||||
color += letters[Math.floor(Math.random() * 16)];
|
||||
}
|
||||
var newDataset = {
|
||||
label: dataset.label,
|
||||
// backgroundColor: 'rgba(99, 255, 132, 0.2)',
|
||||
backgroundColor: color,
|
||||
// borderColor: 'rgba(99, 255, 132, 1)',
|
||||
borderWidth: 1,
|
||||
data: values,
|
||||
}
|
||||
// You add the newly created dataset to the list of `data`
|
||||
chart.data.datasets.push(newDataset);
|
||||
chart.update();
|
||||
this.width = this.calculateWidth();
|
||||
}
|
||||
|
||||
private initChart(): void {
|
||||
|
||||
this.lineChart = new Chart(this.canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [1500, 1600, 1700, 1750, 1800, 1850, 1900, 1950, 1999, 2050],
|
||||
datasets: [{
|
||||
data: [86, 114, 106, 106, 107, 111, 133, 221, 783, 2478],
|
||||
label: "Africa",
|
||||
borderColor: "#3e95cd",
|
||||
fill: false
|
||||
}, {
|
||||
data: [282, 350, 411, 502, 635, 809, 947, 1402, 3700, 5267],
|
||||
label: "Asia",
|
||||
borderColor: "#8e5ea2",
|
||||
fill: false
|
||||
}, {
|
||||
data: [168, 170, 178, 190, 203, 276, 408, 547, 675, 734],
|
||||
label: "Europe",
|
||||
borderColor: "#3cba9f",
|
||||
fill: false
|
||||
}, {
|
||||
data: [40, 20, 10, 16, 24, 38, 74, 167, 508, 784],
|
||||
label: "Latin America",
|
||||
borderColor: "#e8c3b9",
|
||||
fill: false
|
||||
}, {
|
||||
data: [6, 3, 2, 2, 7, 26, 82, 172, 312, 433],
|
||||
label: "North America",
|
||||
borderColor: "#c45850",
|
||||
fill: false
|
||||
}
|
||||
// labels: [1500, 1600, 1700, 1750, 1800, 1850, 1900, 1950, 1999, 2050],
|
||||
labels: [],
|
||||
datasets: [
|
||||
// {
|
||||
// data: [86, 114, 106, 106, 107, 111, 133, 221, 783, 2478],
|
||||
// label: "Africa",
|
||||
// borderColor: "#3e95cd",
|
||||
// fill: false
|
||||
// }, {
|
||||
// data: [282, 350, 411, 502, 635, 809, 947, 1402, 3700, 5267],
|
||||
// label: "Asia",
|
||||
// borderColor: "#8e5ea2",
|
||||
// fill: false
|
||||
// }, {
|
||||
// data: [168, 170, 178, 190, 203, 276, 408, 547, 675, 734],
|
||||
// label: "Europe",
|
||||
// borderColor: "#3cba9f",
|
||||
// fill: false
|
||||
// }, {
|
||||
// data: [40, 20, 10, 16, 24, 38, 74, 167, 508, 784],
|
||||
// label: "Latin America",
|
||||
// borderColor: "#e8c3b9",
|
||||
// fill: false
|
||||
// }, {
|
||||
// data: [6, 3, 2, 2, 7, 26, 82, 172, 312, 433],
|
||||
// label: "North America",
|
||||
// borderColor: "#c45850",
|
||||
// fill: false
|
||||
// }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
suggestedMin: 0, // minimum will be 0, unless there is a lower value.
|
||||
// OR //
|
||||
beginAtZero: true // minimum value will be 0.
|
||||
},
|
||||
|
||||
x: {
|
||||
type: 'time',
|
||||
|
||||
time: {
|
||||
unit: 'minute',
|
||||
displayFormats: {
|
||||
minute: "DD/MM HH:mm",
|
||||
hour: "DD/MM HH:mm",
|
||||
day: "dd/MM",
|
||||
week: "dd/MM",
|
||||
month: "MMMM yyyy",
|
||||
quarter: 'MMMM yyyy',
|
||||
year: "yyyy",
|
||||
}
|
||||
},
|
||||
// ticks: {
|
||||
// labelOffset: 10
|
||||
// }
|
||||
}
|
||||
},
|
||||
}
|
||||
// options: {
|
||||
// title: {
|
||||
// display: true,
|
||||
|
@ -63,6 +287,7 @@ export class GeomonTimeseriesChartComponent implements OnInit {
|
|||
// }
|
||||
// }
|
||||
});
|
||||
this.width = this.calculateWidth() - 20; // add buffer to the left to garantee visualization of last date (tick x-axis)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,4 +305,13 @@ export class GeomonTimeseriesChartComponent implements OnInit {
|
|||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that returns the width of the graph diagram.
|
||||
*/
|
||||
private calculateWidth(): number {
|
||||
return this.canvas.width - this.margin.left - this.margin.right;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue