map.component.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
  2. import { ConfirmationService, MenuItem, MessageService } from 'primeng/api';
  3. import { Extent } from 'ol/extent';
  4. import { Group, Tile, Vector as VectorLayer } from 'ol/layer';
  5. import { OSM, TileWMS, Vector as VectorSource } from 'ol/source';
  6. import GeoJSON from 'ol/format/GeoJSON';
  7. import { transform, transformExtent } from 'ol/proj';
  8. import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style';
  9. import View from 'ol/View';
  10. import { Unit } from '../../../shared/api/endpoints/models/unit';
  11. import { Lastpos } from '../../../shared/api/endpoints/models/lastpos';
  12. import { Drivers } from '../../../shared/api/endpoints/models/drivers';
  13. import { GeneralInfo } from '../../../shared/api/endpoints/models/general-info';
  14. import { Sensor } from '../../../shared/api/endpoints/models/sensor';
  15. import {
  16. HsConfig,
  17. HsMapService,
  18. HsLayerManagerService,
  19. HsLayerEditorService,
  20. HsEventBusService
  21. } from 'hslayers-ng';
  22. import { environment } from '../../../../environments/environment';
  23. import Geometry from 'ol/geom/Geometry';
  24. @Component({
  25. selector: 'app-map',
  26. templateUrl: './map.component.html',
  27. styleUrls: ['./map.component.scss']
  28. })
  29. export class MapComponent implements OnInit, OnDestroy, OnChanges {
  30. @Input('units') units: Array<{ drivers?: Drivers; generalInfo?: GeneralInfo; holder?: any; lastpos?: Lastpos; sensors?: Array<Sensor>; unit?: Unit }>;
  31. mapReady: boolean = false;
  32. dataReady: boolean = false;
  33. unitsLayer: VectorLayer<VectorSource<Geometry>>;
  34. constructor(
  35. private confirmationService: ConfirmationService,
  36. private messageService: MessageService,
  37. public HsConfig: HsConfig,
  38. public HsMapService: HsMapService,
  39. public HsLayerManagerService: HsLayerManagerService,
  40. public HsLayerEditorService: HsLayerEditorService,
  41. public HsEventBusService: HsEventBusService
  42. ) {
  43. this.HsConfig.update({
  44. assetsPath: environment.hslayersAssetsPath,
  45. popUpDisplay: 'click',
  46. proxyPrefix: window.location.hostname.includes('localhost')
  47. ? `${window.location.protocol}//${window.location.hostname}:8085/`
  48. : '/proxy/',
  49. box_layers: [
  50. new Group({
  51. properties: {
  52. title: 'Base layer',
  53. },
  54. layers: [
  55. new Tile({
  56. source: new OSM(),
  57. visible: true,
  58. properties: {
  59. title: 'OpenStreetMap',
  60. base: true,
  61. removable: false
  62. }
  63. })
  64. ]
  65. })
  66. ],
  67. //default_layers: this.loadLayers(),
  68. componentsEnabled: {
  69. sidebar: false,
  70. toolbar: false,
  71. guiOverlay: true,
  72. drawToolbar: false,
  73. searchToolbar: false,
  74. measureToolbar: false,
  75. sensors: false,
  76. crossfilter: false,
  77. geolocationButton: false,
  78. tracking: false,
  79. mapControls: true,
  80. basemapGallery: true
  81. },
  82. panelsEnabled: {
  83. info: false, //(true by default),
  84. layermanager: false
  85. },
  86. sidebarPosition: 'invisible',
  87. queryPoint: 'hidden',
  88. default_view: new View({
  89. maxZoom: 17
  90. // center: [1873444.3416929364, 6286508.646897761], // Latitude longitude to Spherical Mercator
  91. // extent: [1871197.0792499082, 6282949.4051418, 1873509.6915773677, 6287134.61866585],
  92. // multiWorld: false,
  93. // zoom: 6
  94. })
  95. });
  96. }
  97. ngOnInit(): void {
  98. }
  99. ngOnChanges(changes: SimpleChanges): void {
  100. if (changes['units']) {
  101. //this.dataReady = true;
  102. //if (this.mapReady)
  103. this.HsMapService.loaded().then((map) => {
  104. this.initMap();
  105. let unitsExtent: Extent = this.unitsLayer.getSource().getExtent();
  106. this.HsMapService.map.getView().fit(unitsExtent, { size: this.HsMapService.map.getSize() });
  107. this.HsMapService.map.on("pointermove", function (evt) {
  108. var hit = this.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
  109. return true;
  110. });
  111. if (hit) {
  112. this.getTargetElement().style.cursor = 'pointer';
  113. } else {
  114. this.getTargetElement().style.cursor = '';
  115. }
  116. });
  117. });
  118. }
  119. }
  120. /**
  121. * Unsubscribe after leaving
  122. */
  123. ngOnDestroy(): void {
  124. }
  125. initMap(): void {
  126. this.unitsLayer = this.initUnitsLayer(this.HsMapService.map);
  127. this.HsMapService.map.addLayer(this.unitsLayer);
  128. // this.HsMapService.map.on('click', function (evt) {
  129. // var feature = this.HsMapService.map.forEachFeatureAtPixel(evt.pixel,
  130. // function (feature) {
  131. // return feature;
  132. // });
  133. // if (feature) {
  134. // let unitId = feature.getProperties()['unitId'];
  135. // window.open('/#/dashboard / unit /' + unitId);
  136. // }
  137. // })
  138. }
  139. /**
  140. * Crete vector layer from units positions
  141. */
  142. initUnitsLayer(map: any): any {
  143. var geoJsonUnits = {
  144. 'type': 'FeatureCollection',
  145. 'crs': {
  146. 'type': 'name',
  147. 'properties': {
  148. 'name': 'EPSG:3857',
  149. }
  150. }
  151. };
  152. geoJsonUnits['features'] = this.units ? this.units.filter(u => (u.lastpos.position.x > 0)).map(u => this.getUnitPos(u.lastpos, u.unit)) : [];
  153. const vectorSource = new VectorSource({
  154. features: new GeoJSON().readFeatures(geoJsonUnits),
  155. });
  156. vectorSource.on('addfeature', function () {
  157. map.getView().fit(vectorSource.getExtent());
  158. });
  159. const vectorLayer = new VectorLayer({
  160. source: vectorSource,
  161. style: this.styleFunction,
  162. properties: {
  163. popUp: {
  164. displayFunction: function (feature) {
  165. return `<ul>
  166. <li>Unit name &nbsp; ${feature.get('title')}</li>
  167. <li>Unit ID &nbsp; ${feature.get('id')}</li>
  168. </ul>
  169. <button class="p-button-primary" style="display: block; margin: auto;"><a class="white" href="/dashboard/unit/${feature.get('id')}" target="_blank">Open Unit detail...</a></button>
  170. `;
  171. }
  172. // attributes: [
  173. // {
  174. // attribute: 'id',
  175. // label: 'Unit ID'
  176. // },
  177. // {
  178. // attribute: 'online',
  179. // label: 'Online',
  180. // displayFunction: function (val) {
  181. // return '<span class="' + (val ? 'far fa-check-square' : 'far fa-square') + '"></span>';
  182. // }
  183. // },
  184. // {
  185. // attribute: 'test',
  186. // label: 'test'
  187. // },
  188. // {
  189. // attribute: 'id',
  190. // label: 'Detail',
  191. // displayFunction: function (val) {
  192. // return '<a class="white" href="/#/dashboard/unit/' + val + '" target="_blank">open unit detail...</a>';
  193. // }
  194. // }
  195. // ]
  196. }
  197. }
  198. });
  199. return vectorLayer;
  200. }
  201. styleFunction(feature: any): Style {
  202. return new Style({
  203. image: new CircleStyle({
  204. radius: 5,
  205. fill: new Fill({
  206. color: 'red'
  207. }),
  208. stroke: new Stroke({
  209. color: 'blue',
  210. width: 2
  211. })
  212. })
  213. })
  214. }
  215. getUnitPos(pos: Lastpos, unit: Unit): any {
  216. return {
  217. "type": "Feature",
  218. "geometry": {
  219. "type": "Point",
  220. "coordinates": [pos.position.x, pos.position.y]
  221. },
  222. "properties": {
  223. "id": unit.unitId,
  224. "title": unit.description,
  225. "online": pos.attributes.is_online,
  226. "moving": pos.attributes.is_moving
  227. }
  228. }
  229. }
  230. }