Skip to content
Snippets Groups Projects
WeatherMap.vue 5.15 KiB

<template>
    <div id="weatherContainer">
        
        <Legend id="legend" @stationUpdate="stationupdate" @layerVisibility="layerVisibility" :mapProperties="mapProperties"></Legend>
        
        <div ref="weathermap" id="weathermap" />

        <div ref="popup" class="ol-popup">
            <a href="#" ref="popup-closer" class="ol-popup-closer"></a>
            <div ref="popup-content">
                
            </div>
            <StationChartPopup ref="StationChartPopup"/>
        </div>
    </div>
</template>

<style scoped>
    #weatherContainer{
        width:100%;
        height:100%;
        position:relative;
    }
    #legend{
      width:20%;
      height:100%;
      position:relative;
      float:right;
    }
    #weathermap{
      width:80%;
      height:100%;
      position:relative;
      float:right;
    }

    .ol-popup {
        position: absolute;
        background-color: white;
        box-shadow: 0 1px 4px rgba(0,0,0,0.2);
        padding: 15px;
        border-radius: 10px;
        border: 1px solid #cccccc;
        bottom: 12px;
        left: -50px;
        min-width: 280px;
      }
      .ol-popup:after, .ol-popup:before {
        top: 100%;
        border: solid transparent;
        content: " ";
        height: 0;
        width: 0;
        position: absolute;
        pointer-events: none;
      }
      .ol-popup:after {
        border-top-color: white;
        border-width: 10px;
        left: 48px;
        margin-left: -10px;
      }
      .ol-popup:before {
        border-top-color: #cccccc;
        border-width: 11px;
        left: 48px;
        margin-left: -11px;
      }
      .ol-popup-closer {
        text-decoration: none;
        position: absolute;
        top: 2px;
        right: 8px;
      }
      .ol-popup-closer:after {
        content: "✖";
      }

</style>

<script lang="ts">
import {Vue, Ref, Component, Watch } from 'vue-property-decorator';
import View from 'ol/View';
import Map from 'ol/Map';
import OSM from 'ol/source/OSM';
import Overlay from 'ol/Overlay';
import TileLayer from 'ol/layer/Tile';
import { fromLonLat} from 'ol/proj';
import 'ol/ol.css';
import StationLayer from './StationLayer';
import MapProperties from './MapProperties';
import StationChartPopup from './StationChartPopup.vue';
import Legend from './Legend.vue';

@Component({components:{Legend, StationChartPopup}})
export default class WeatherMap extends Vue{
 
    @Ref('weathermap') readonly targetElement!: HTMLElement;
    private map!: Map;   
    private projection: string = 'EPSG:3857'; //4236
    private mapProperties: MapProperties = new MapProperties(null, "");
    private stationLayer: StationLayer;
    @Ref('StationChartPopup') stationChartPopup: StationChartPopup;
    
    @Ref('popup') container: HTMLElement;
    @Ref('popup-content') content: HTMLElement;
    @Ref('popup-closer') closer: HTMLElement;
    
    private overlay:Overlay;

    public mounted(): void{
        this.overlay = new Overlay({
            element: this.container,
            autoPan: true,
            autoPanAnimation: {
                duration: 250,
            },
        });

        this.map = new Map({
            target: this.targetElement,
            layers: [
                new TileLayer({
                    source: new OSM()
                })
            ],
            view: new View({
                zoom: 6.49,
                center: fromLonLat([4.0, 51.3]),
                constrainResolution: true,
                projection: this.projection
            }),
            overlays: [this.overlay],
        });

        this.mapProperties = new MapProperties(this.map, this.projection);
        
        this.appendStationLayer();

        this.map.on('click', (evt) => {
            const coordinate = evt.coordinate;
            var openPopup: boolean = false;
            
            this.map.forEachFeatureAtPixel(evt.pixel, (feature, layer)=> {
                
                if(layer.getClassName()===StationLayer.layerName){
                    this.stationChartPopup.renderGraph(this.stationLayer.getTemperatureSeriesFromFeature(feature));
                    openPopup = true;
                    this.content.innerHTML = '<p>Station: ' + feature.get("id") + '</p>';
                }else{
                    
                }
            });

            if(openPopup){
                
                this.overlay.setPosition(coordinate);
            }else{
                this.closePopUp();
            }

        });

        this.closer.onclick = () => {
            this.closePopUp();
        };
    }

    private closePopUp():void{
        this.overlay.setPosition(undefined);
        this.closer.blur();
    }

    private appendStationLayer(){
        this.stationLayer = new StationLayer(this.mapProperties);
        this.map.addLayer(this.stationLayer.getLayer());
    }

    public stationupdate(event){
        this.stationLayer.newYear(event); 
    }

    protected layerVisibility(isVisible: boolean, layer:string):void{
        //this.stationLayer.getLayer().setVisible(this.visibleLayers.has(StationLayer.layerName));
        if(layer=='stationLayer'){
            this.stationLayer.getLayer().setVisible(isVisible);
        }
    }
    

};
</script>