Project

General

Profile

1
import { MapCountryData } from '../../domain/map-country-data';;
2

    
3
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
4
import { CountryOverview } from '../../domain/overview-data';
5

    
6
import { DataService } from '../../services/data.service';
7
import { Router } from '@angular/router';
8
import {CountryMapData, JoinedMapData, OverviewMapData, SelectedCountry} from '../../domain/overview-map-data';
9
import { latlong } from '../../domain/countries-lat-lon';
10
import { DataHandlerService } from '../../services/data-handler.service';
11

    
12
import * as echarts from 'echarts';
13
import {
14
  datasetColor,
15
  datasetTooltipColor, journalsColor, journalsTooltipColor, journalsBackgroundColor, policiesColor, policiesTooltipColor,
16
  publicationColor,
17
  publicationTooltipColor,
18
  repositoriesColor,
19
  repositoriesTooltipColor,
20
  gradientStartColor
21
} from '../../chart-palettes';
22

    
23
declare var require: any;
24

    
25
const mapWorld = require('echarts/map/json/world.json');
26

    
27
@Component({
28
  selector: 'app-europe-map-overview',
29
  templateUrl: './europe-map-overview.component.html',
30
})
31

    
32
export class EuropeMapOverviewComponent implements OnInit {
33

    
34
  private gradientStartColor = gradientStartColor;
35

    
36
  countries: CountryOverview[];
37

    
38
  @Output() emitSelectedCountry: EventEmitter<any> = new EventEmitter();
39

    
40
  activeView: string = 'publications';
41
  seriesColor: string = publicationColor;
42
  seriesName: string = 'OA publications';
43

    
44
  // tooltipBackgroundColor: string = '#EC4386';
45
  tooltipBackgroundColor: string = publicationTooltipColor;
46
  tooltipBorderColor: string = '#000';
47

    
48
  options = {};
49

    
50
  overviewMapData: OverviewMapData;
51

    
52
  countriesLatLong = latlong;
53

    
54
  joinedPublicationsMap: Map<string, JoinedMapData>;
55
  joinedDatasetsMap: Map<string, JoinedMapData>;
56
  joinedRepositoriesMap: Map<string, JoinedMapData>;
57
  joinedJournalsMap: Map<string, JoinedMapData>;
58

    
59
  constructor(private dataService: DataService,
60
              private dataHandlerService: DataHandlerService,
61
              private router: Router) {}
62

    
63
  ngOnInit(): void {
64

    
65
    echarts.registerMap('world', mapWorld);
66

    
67
    if (this.isEmbedRoute()) {
68
      const body = document.getElementsByTagName('body')[0];
69
      body.classList.remove('header_sticky');
70
    }
71

    
72
    this.dataService.getOverviewMapData().subscribe(
73
      rawData => {
74
        // console.log('==== Map RawData ====', rawData);
75
        this.overviewMapData = this.dataHandlerService.convertRawMapDataToMapData(rawData);
76
        this.joinedPublicationsMap = this.dataHandlerService.createJoinedPublicationsCountryMap(rawData);
77
        this.joinedDatasetsMap = this.dataHandlerService.createJoinedDatasetsCountryMap(rawData);
78
        this.joinedRepositoriesMap = this.dataHandlerService.createJoinedRepositoriesCountryMap(rawData);
79
        this.joinedJournalsMap = this.dataHandlerService.createJoinedJournalsCountryMap(rawData);
80

    
81
        // console.log('Country map data', this.overviewMapData[this.activeView]);
82
        this.loadMap(this.overviewMapData[this.activeView], this.seriesColor, this.seriesColor);
83
      },
84
      error => {
85
        console.log(error);
86
      }
87
    );
88
  }
89

    
90
  changeView(view: string) {
91
    this.activeView = view;
92

    
93
    if (this.activeView === 'publications') {
94
      this.seriesColor = publicationColor;
95
      this.seriesName = 'OA publications';
96
      this.tooltipBackgroundColor = publicationTooltipColor;
97
      this.tooltipBorderColor = '#000';
98
    } else if (this.activeView === 'datasets') {
99
      this.seriesColor = datasetColor;
100
      this.seriesName = 'OA datasets';
101
      this.tooltipBackgroundColor = datasetTooltipColor;
102
      this.tooltipBorderColor = '#000';
103
    } else if (this.activeView === 'repositories') {
104
      this.seriesColor = repositoriesColor;
105
      this.seriesName = 'OA repositories';
106
      this.tooltipBackgroundColor = repositoriesTooltipColor;
107
      this.tooltipBorderColor = '#000';
108
    } else if (this.activeView === 'journals') {
109
      this.seriesColor = journalsColor;
110
      this.seriesName = 'OA journals';
111
      this.tooltipBackgroundColor = journalsTooltipColor;
112
      this.tooltipBorderColor = '#000';
113
    } else {
114
      this.seriesColor = policiesColor;
115
      this.seriesName = 'OA policies';
116
      this.tooltipBackgroundColor = policiesTooltipColor;
117
      this.tooltipBorderColor = '#000';
118
    }
119
    this.loadMap(this.overviewMapData[view], this.seriesColor, this.seriesName);
120
  }
121

    
122
  loadMap(countryMapData: CountryMapData[], seriesColor: string, seriesName: string) {
123

    
124
    this.options = {
125
      title : {
126
        // text: 'World Population (2011)',
127
        // subtext: 'From Gapminder',
128
        left: 'center',
129
        top: 'top',
130
        textStyle: {
131
          color:  '#fff'
132
        }
133
      },
134
      responsive: true,
135
      tooltip : {
136
        trigger: 'item',
137
        // position: 'top',
138
        // formatter: '<strong>{b}</strong><br> {c2} {a}',
139
        // backgroundColor: '#f6c4d8',
140
        // borderColor: '#bf1d5e',
141
        // borderWidth: 0.2
142
      },
143
      visualMap: {
144
        show: false,
145
        min: 0,
146
        // max: max,
147
        max: 80000,
148
        inRange: {
149
          // symbolSize: [6, 60]
150
          // symbolSize: [0, 6]
151
        }
152
      },
153
      geo: {
154
        // name:  'World Population (2010)',
155
        type: 'map',
156
        map: 'world',
157
        // center: [15.2551, 54.5260],
158
        center: [14, 51],
159
        // zoom: 4.7,
160
        zoom: 4.3,
161
        // zoom: 6,
162
        // roam: true,
163
        label: {
164
          emphasis: {
165
            show: false
166
          }
167
        },
168
        itemStyle: {
169
          normal: {
170
            // color: 'rgba(139,151,167,0.4)',
171
            // borderColor: '#000',
172
            borderColor: '#fff',
173
            borderWidth: 0.5,
174
            areaColor: 'rgba(139,151,167,0.6)',
175
            // areaStyle: {
176
            //   color: 'rgba(139,151,167,0.2)'
177
            // }
178
          },
179
          emphasis: {
180
            // color: 'rgba(139,151,167,0.4)',
181
            // borderColor: '#000',
182
            borderColor: '#fff',
183
            borderWidth: 0.5,
184
            areaColor: 'rgba(139,151,167,0.8)',
185
            // areaStyle: {
186
            //   color: 'rgba(139,151,167,0.2)'
187
            // }
188
          }
189
        }
190
        // itemStyle: {
191
        //   // areacolor: '#ffffff',
192
        //   // bordercolor: '#111',
193
        //   // borderWidth: 1,
194
        //   // normal: {
195
        //   //   // areacolor: '#323c48',
196
        //   //   areacolor: '#ffffff',
197
        //   //   bordercolor: '#111'
198
        //   // },
199
        //   // emphasis: {
200
        //   //   areacolor: '#2a333d'
201
        //   // }
202
        // }
203
      },
204
      series : [
205
        {
206
          type: 'scatter',
207
          coordinateSystem: 'geo',
208
          name: seriesName,
209
          label: {
210
            show: true,
211
            position: 'inside',
212
            color: '#fff',
213
            opacity: 1,
214
            // formatter: '{@[2]}',
215
            formatter: (params => {
216
              return params.data.value[2].toLocaleString();
217
            }),
218
            textBorderColor: '#000',
219
            textBorderWidth: '2',
220
            fontSize: 15
221
            // formatter: '{b}: {@score}'
222
          },
223
          // activeOpacity: 0.6,
224
          data: countryMapData.map((itemOpt) => {
225
            // console.log('itemOpt.code', itemOpt.code);
226
            return {
227
              name: itemOpt.name,
228
              value: [
229
                this.countriesLatLong.get(itemOpt.code).longitude,
230
                this.countriesLatLong.get(itemOpt.code).latitude,
231
                itemOpt.value
232
              ],
233
              // label: {
234
              //   emphasis: {
235
              //     position: 'right',
236
              //     show: true
237
              //   }
238
              // },
239
              itemStyle: {
240
                normal: {
241
                  color:  seriesColor,
242
                  // color:  {
243
                  //   type: 'linear',
244
                  //   x: 0,
245
                  //   y: 0,
246
                  //   x2: 0,
247
                  //   y2: 1,
248
                  //   colorStops: [{
249
                  //     offset: 0, color: gradientStartColor // color at 0% position
250
                  //   }, {
251
                  //     offset: 1, color: seriesColor // color at 100% position
252
                  //   }],
253
                  //   global: false // false by default
254
                  // },
255
                  // color:  '#f8d5e3',
256
                  // opacity: 0.5,
257
                  borderColor: seriesColor,
258
                  borderWidth: 2
259
                }
260
              }
261
            };
262
          }),
263
          symbolSize: value => {
264
            // console.log('Math.sqrt(value[2]) / 1000: ' + (Math.sqrt(value[2]) / 1000) );
265
            // return Math.sqrt(value[2]) / 10;
266
            return Math.sqrt(value[2]) / 10 * this.resizeFactor(countryMapData);
267
            // return Math.sqrt(value[2]) / 10;
268
          },
269
          tooltip : {
270
            trigger: 'item',
271
            position: 'top',
272
            formatter: (params => {
273
              // console.log('params: ', params);
274
              // let bla = '<strong>' + params.data.name + '</strong><br>';
275
              // bla += params.data.value[2].toLocaleString() + ' ' + params.seriesName;
276
              // return bla;
277
              return this.createTooltip(params);
278
            }),
279
            backgroundColor: this.tooltipBackgroundColor,
280
            borderColor: this.tooltipBorderColor,
281
            borderWidth: 0.2
282
          },
283
        }
284
      ]
285
    };
286
  }
287

    
288
  onChartClick(event: any, type: string) {
289
    // console.log('chart event:', type, event);
290
    // console.log('country:', event.name);
291

    
292
    const selectedCountry: SelectedCountry = new SelectedCountry();
293
    selectedCountry.name = event.name;
294
    selectedCountry.code = this.joinedPublicationsMap.get(event.name).countryCode;
295

    
296
    // console.log('Selected country', selectedCountry);
297
    this.emitSelectedCountry.emit(selectedCountry);
298
  }
299

    
300
  // selectedCountry(countryName: string) {
301
  //   this.emitSelectedCountry.emit(countryName);
302
  // }
303

    
304
  isEmbedRoute() {
305
    return (this.router.url === '/overview-map-embed');
306
  }
307

    
308
  resizeFactor(countryMapData: CountryMapData[]) {
309

    
310
    let max = 0;
311
    for (const countryData of countryMapData) {
312
      if (countryData.value > max) {
313
        max = countryData.value;
314
      }
315
    }
316
    // console.log('resizeFactor', 100 / (Math.sqrt(max) / 10));
317
    return 100 / (Math.sqrt(max) / 10);
318
  }
319

    
320
  createTooltip(params: any) {
321

    
322
    // console.log('params: ', params);
323
    // console.log('params.name: ', params.name);
324

    
325
    let tooltip = '<div style="padding:10px">';
326

    
327
    tooltip += '<div class="uk-margin-small" style="font-weight: 600;">' + params.name + '</div>';
328

    
329
    if (this.activeView === 'publications') {
330

    
331
      tooltip += '<div class="numbers">';
332
      tooltip += '<div class="indicator">' +
333
        '<span class="number">' + params.data.value[2].toLocaleString() + '</span>' +
334
        '<span><i>OA publications</i> affiliated <br>to an organization in the country</span></div>';
335

    
336
      tooltip += '<div class="indicator uk-margin-small-top">' +
337
        '<span class="number">' + this.joinedPublicationsMap.get(params.name).deposited.toLocaleString() + '</span>' +
338
        '<span><i>OA publications</i> from <br>institutional repositories</span></div>';
339

    
340
      tooltip += '</div>';
341

    
342
    } else if (this.activeView === 'datasets') {
343

    
344
      tooltip += '<div class="numbers">';
345
      tooltip += '<div class="indicator">' +
346
        '<span class="number">' + params.data.value[2].toLocaleString() + '</span>' +
347
        '<span><i>OA datasets</i> affiliated <br>to an organization in the country</span></div>';
348

    
349
      tooltip += '<div class="indicator uk-margin-small-top">' +
350
        '<span class="number">' + this.joinedDatasetsMap.get(params.name).deposited.toLocaleString() + '</span>' +
351
        '<span><i>OA datasets</i> from <br>institutional repositories</span></div>';
352

    
353
      tooltip += '</div>';
354

    
355
    } else if (this.activeView === 'repositories') {
356

    
357
      tooltip += '<div class="numbers">';
358
      tooltip += '<div class="indicator">' +
359
        '<span class="number">' + params.data.value[2].toLocaleString() + '</span>' +
360
        '<span><i>repositories</i> from <br>openDOAR & re3data</span></div>';
361

    
362
      tooltip += '<div class="indicator uk-margin-small-top">' +
363
        '<span class="number">' + this.joinedRepositoriesMap.get(params.name).simple.toLocaleString() + '</span>' +
364
        '<span><i>repositories</i></span></div>';
365

    
366
      tooltip += '</div>';
367

    
368
    } else if (this.activeView === 'journals') {
369

    
370
      tooltip += '<div class="numbers">';
371
      tooltip += '<div class="indicator">' +
372
        '<span class="number">' + params.data.value[2].toLocaleString() + '</span>' +
373
        '<span><i>journals</i> from DOAJ</span></div>';
374

    
375
      tooltip += '<div class="indicator uk-margin-small-top">' +
376
        '<span class="number">' + this.joinedJournalsMap.get(params.name).simple.toLocaleString() + '</span>' +
377
        '<span><i>journals</i></span></div>';
378

    
379
      tooltip += '</div>';
380

    
381
    } else {
382

    
383
      tooltip += '<div class="numbers">';
384
      tooltip += '<div class="indicator">' +
385
        '<span class="number">' + params.data.value[2].toLocaleString() + '</span>' +
386
        '<span>organizations with <br><i>OA policies</i></span></div>';
387

    
388
      tooltip += '</div>';
389
    }
390

    
391
    tooltip += '</div>';
392
    return tooltip;
393
  }
394
}
(8-8/12)