import { Injectable } from '@angular/core' ; import VectorSource from 'ol/source/Vector' ; import { Circle , Icon , RegularShape , Style } from 'ol/style' ; import { Cluster , ImageArcGISRest , ImageStatic , ImageWMS , Source , TileArcGISRest , WMTS , XYZ , } from 'ol/source' ; import { Feature } from 'ol' ; import { GeoJSON } from 'ol/format' ; import { Geometry } from 'ol/geom' ; import { Image as ImageLayer , Tile , Vector as VectorLayer } from 'ol/layer' ; import { HsConfig } from '../../config.service' ; import { HsLayerUtilsService } from '../utils/layer-utils.service' ; import { HsLayoutService } from '../layout/layout.service' ; import { HsLogService } from '../../common/log/log.service' ; import { HsMapService } from '../map/map.service' ; import { HsUtilsService } from '../utils/utils.service' ; import { Layer } from 'ol/layer' ; import { getAttribution , getBase , getDefinition , getDimensions , getLegends , getMetadata , getName , getPath , getShowInLayerManager , getSld , getSubLayers , getTitle , getWfsUrl , getWorkspace , } from '../../common/layer-extensions' ; const LCLSTORAGE_EXPIRE = 5000 ; @ Injectable ( { providedIn : 'root' , } ) export class HsSaveMapService { public internalLayers : Layer < Source > [ ] = [ ] ; constructor ( public hsConfig , public HsMapService , public HsUtilsService , public HsLayoutService , public HsLogService , public HsLayerUtilsService ) { window . addEventListener ( 'beforeunload' , ( e ) => { if ( hsConfig . saveMapStateOnReload ) { this . save2storage ( e ) ; } } ) ; } param { Ol . map } map param { object } compoData param { object } userData param { object } statusData returns { object } map2json ( map , compoData , userData , statusData ) { const groups = { } ; for ( const g of statusData . groups || [ ] ) { if ( g . r || g . w ) { groups [ g . roleName ] = ( g . r ? 'r' : '' ) + ( g . w ? 'w' : '' ) ; } } if ( groups . guest == undefined ) { groups . guest = 'r' ; } let bbox = compoData . bbox ; if ( compoData . bbox && ! Array . isArray ( compoData . bbox ) ) { bbox = [ compoData . bbox . east , compoData . bbox . south , compoData . bbox . west , compoData . bbox . north , ] ; } const json = { abstract : compoData . abstract , title : compoData . title , keywords : compoData . keywords , extent : bbox , user : { address : userData . address , city : userData . city , country : userData . country , email : userData . email || 'none@none' , name : userData . name , organization : userData . organization , phone : userData . phone , position : userData . position , postalcode : userData . postalcode , state : userData . state , } , groups : groups , } ; const currentProj = this . HsMapService . getCurrentProj ( ) ; json . scale = currentProj . getMetersPerUnit ( ) ; json . projection = currentProj . getCode ( ) . toLowerCase ( ) ; const center = map . getView ( ) . getCenter ( ) ; if ( center ) { json . center = [ center [ 0 ] , center [ 1 ] ] ; } json . units = currentProj . getUnits ( ) ; if ( map . maxExtent ) { json . maxExtent = { } ; json . maxExtent . left = map . maxExtent . left ; json . maxExtent . bottom = map . maxExtent . bottom ; json . maxExtent . right = map . maxExtent . right ; json . maxExtent . top = map . maxExtent . top ; } json . layers = this . layers2json ( compoData . layers ) ; json . current_base_layer = this . getCurrentBaseLayer ( ) ; return json ; } param { Map } map returns { object } getCurrentBaseLayer ( ) { let current_base_layer = null ; for ( const lyr of this . HsMapService . getLayersArray ( ) ) { if ( ( getShowInLayerManager ( lyr ) == undefined || getShowInLayerManager ( lyr ) == true ) && getBase ( lyr ) == true && lyr . getVisible ( ) ) { current_base_layer = { title : getTitle ( lyr ) , } ; } } return current_base_layer ; } param { Array } layers returns { Array } layers2json ( layers ) { const json = [ ] ; layers . forEach ( ( layer ) => { const l = this . layer2json ( layer ) ; if ( l ) { json . push ( l ) ; } } ) ; return json ; } param { object } layer param { boolean } pretty returns { string } layer2string ( layer , pretty ) { const json = this . layer2json ( layer ) ; const text = JSON . stringify ( json , pretty ) ; return text ; } param s returns { object } serializeStyle ( style ) { const s = Array . isArray ( style ) ? style [ 0 ] : style ; const o = { } ; const ima = { } ; if ( s . getFill ( ) && s . getFill ( ) !== null ) { o . fill = s . getFill ( ) . getColor ( ) ; } if ( s . getStroke ( ) && s . getStroke ( ) !== null ) { o . stroke = { color : s . getStroke ( ) . getColor ( ) , width : s . getStroke ( ) . getWidth ( ) , } ; } if ( s . getImage ( ) && s . getImage ( ) !== null ) { const style_img = s . getImage ( ) ; if ( this . HsUtilsService . instOf ( style_img , RegularShape ) ) { const regShape = style_img as RegularShape ; if ( regShape . getFill ( ) ) { ima . fill = regShape . getFill ( ) . getColor ( ) ; } if ( regShape . getStroke ( ) ) { ima . stroke = { color : regShape . getStroke ( ) . getColor ( ) , width : regShape . getStroke ( ) . getWidth ( ) , } ; } ima . radius = regShape . getRadius ( ) ; } if ( this . HsUtilsService . instOf ( style_img , Icon ) && typeof ( style_img as Icon ) . getSrc ( ) === 'string' && ! ( style_img as Icon ) . getSrc ( ) . startsWith ( 'data:image' ) ) { ima . src = this . HsUtilsService . proxify ( ( style_img as Icon ) . getSrc ( ) ) ; } if ( this . HsUtilsService . instOf ( style_img , Circle ) ) { ima . type = 'circle' ; } if ( this . HsUtilsService . instOf ( style_img , Icon ) ) { ima . type = 'icon' ; } o . image = ima ; } return o ; } param layer returns layer2json ( layer ) { const json = { metadata : getMetadata ( layer ) || { } , } ; json . visibility = layer . getVisible ( ) ; json . opacity = layer . getOpacity ( ) ; json . base = getBase ( layer ) ?? false ; json . title = getTitle ( layer ) ; if ( getTitle ( layer ) == undefined ) { this . HsLogService . warn ( 'Layer title undefined' , layer ) ; } json . path = getPath ( layer ) ; if ( layer . getExtent ( ) ) { const ex = layer . getExtent ( ) ; json . maxExtent = { left : ex [ 0 ] , bottom : ex [ 3 ] , right : ex [ 2 ] , top : ex [ 1 ] , } ; } if ( this . HsUtilsService . instOf ( layer , Tile ) || this . HsUtilsService . instOf ( layer , ImageLayer ) ) { const src = layer . getSource ( ) ; if ( layer . getMaxResolution ( ) !== null ) { json . maxResolution = layer . getMaxResolution ( ) ; } if ( layer . getMinResolution ( ) !== null ) { json . minResolution = layer . getMinResolution ( ) ; } json . displayInLayerSwitcher = getShowInLayerManager ( layer ) ; if ( getDimensions ( layer ) ) { json . dimensions = getDimensions ( layer ) ; } if ( this . HsUtilsService . instOf ( src , XYZ ) ) { json . className = 'XYZ' ; } if ( this . HsUtilsService . instOf ( src , ImageArcGISRest ) || this . HsUtilsService . instOf ( src , TileArcGISRest ) ) { json . className = 'ArcGISRest' ; json . singleTile = this . HsUtilsService . instOf ( src , ImageArcGISRest ) ; } if ( this . HsUtilsService . instOf ( src , ImageStatic ) ) { json . className = 'StaticImage' ; json . extent = ( src as ImageStatic ) . getImageExtent ( ) ; } if ( this . HsLayerUtilsService . isLayerWMS ( layer ) ) { json . className = 'HSLayers.Layer.WMS' ; json . singleTile = this . HsUtilsService . instOf ( src , ImageWMS ) ; if ( getLegends ( layer ) ) { json . legends = [ ] ; const legends = getLegends ( layer ) ; if ( Array . isArray ( legends ) ) { json . legends = legends . map ( ( l ) => encodeURIComponent ( l ) ) ; } if ( typeof legends == 'string' ) { json . legends = [ legends ] ; } } if ( src . getProjection ( ) ) { json . projection = src . getProjection ( ) . getCode ( ) . toLowerCase ( ) ; } json . params = this . HsLayerUtilsService . getLayerParams ( layer ) ; json . subLayers = getSubLayers ( layer ) ; json . metadata . styles = src . get ( 'styles' ) ; } json . url = encodeURIComponent ( this . HsLayerUtilsService . getURL ( layer ) ) ; if ( getAttribution ( layer ) ) { json . attributions = getAttribution ( layer ) ; } if ( this . HsUtilsService . instOf ( src , WMTS ) ) { const wmts = src as WMTS ; json . className = 'HSLayers.Layer.WMTS' ; json . matrixSet = wmts . getMatrixSet ( ) ; json . layer = wmts . getLayer ( ) ; json . format = wmts . getFormat ( ) ; json . info_format = layer . get ( 'info_format' ) ; json . url = wmts . getUrls ( ) [ 0 ] ; } } if ( this . HsUtilsService . instOf ( layer , VectorLayer ) ) { let src = layer . getSource ( ) ; if ( this . HsLayerUtilsService . isLayerClustered ( layer ) ) { src = ( src as Cluster ) . getSource ( ) ; } json . name = getName ( layer ) ; json . className = 'Vector' ; const definition = getDefinition ( layer ) ; if ( definition && definition . url ) { json . protocol = { url : encodeURIComponent ( definition . url ) , format : definition . format , } ; json . workspace = getWorkspace ( layer ) ; delete json . features ; } else { if ( getWfsUrl ( layer ) ) { json . protocol = { url : getWfsUrl ( layer ) , format : 'hs.format.externalWFS' , } ; } else { try { json . features = this . getFeaturesJson ( ( src as VectorSource < Geometry > ) . getFeatures ( ) ) ; } catch ( ex ) { } } } json . maxResolution = layer . getMaxResolution ( ) ; json . minResolution = layer . getMinResolution ( ) ; json . projection = 'epsg:4326' ; if ( getSld ( layer ) != undefined ) { json . style = getSld ( layer ) ; } else if ( this . HsUtilsService . instOf ( ( layer as VectorLayer < VectorSource < Geometry > > ) . getStyle ( ) , Style ) ) { json . style = this . serializeStyle ( ( layer as VectorLayer < VectorSource < Geometry > > ) . getStyle ( ) as Style ) ; } } return json ; } param features returns getFeaturesJson ( features ) { const f = new GeoJSON ( ) ; const featureProjection = this . HsMapService . getCurrentProj ( ) . getCode ( ) ; return f . writeFeaturesObject ( features , { dataProjection : 'EPSG:4326' , featureProjection , } ) ; } param { $element } $element param { object } localThis param { boolean } newRender generateThumbnail ( $element , localThis , newRender ? ) { /**
         *
         */ function rendered ( ) { const canvas = this . HsMapService . getCanvases ( ) [ 0 ] ; const canvas2 = document . createElement ( 'canvas' ) ; const width = 256 , height = 256 ; canvas2 . style . width = width + 'px' ; canvas2 . style . height = height + 'px' ; canvas2 . width = width ; canvas2 . height = height ; const ctx2 = canvas2 . getContext ( '2d' ) ; ctx2 . drawImage ( canvas , canvas . width / 2 - height / 2 , canvas . height / 2 - width / 2 , width , height , 0 , 0 , width , height ) ; try { $element . setAttribute ( 'src' , canvas2 . toDataURL ( 'image/png' ) ) ; this . thumbnail = canvas2 . toDataURL ( 'image/jpeg' , 0.8 ) ; } catch ( e ) { this . HsLogService . warn ( e ) ; $element . setAttribute ( 'src' , this . HsUtilsService . getAssetsPath ( ) + 'img/notAvailable.png' ) ; } $element . style . width = width + 'px' ; $element . style . height = height + 'px' ; } if ( this . HsLayoutService . mainpanel == 'save-map' || this . HsLayoutService . mainpanel == 'permalink' || this . HsLayoutService . mainpanel == 'statusCreator' ) { if ( $element === null ) { return ; } $element . setAttribute ( 'crossOrigin' , 'Anonymous' ) ; rendered . bind ( localThis ) ; this . HsMapService . map . once ( 'postcompose' , rendered ) ; if ( newRender ) { this . HsMapService . map . renderSync ( ) ; } else { rendered ( ) ; } } } save2storage ( evt ) { const data = { expires : new Date ( ) . getTime ( ) + LCLSTORAGE_EXPIRE , layers : this . HsMapService . getLayersArray ( ) . filter ( ( lyr ) => ! this . internalLayers . includes ( lyr ) ) . map ( ( lyr ) => this . layer2json ( lyr ) ) , } ; localStorage . setItem ( 'hs_layers' , JSON . stringify ( data ) ) ; } }