import { Feature, GeoJsonObject, Point } from 'geojson'; import L from 'leaflet'; import { Facility } from '@creedinteractive/onguard-models'; import { PieMarker, ArcData } from './pie-marker'; import { animatedBezier } from './lines'; import { BezierCurve } from './bezier-curve'; import { latLng } from 'leaflet'; export interface FlowLayerOptions extends L.GeoJSONOptions { } export class FlowLayer extends L.GeoJSON { private primaryMarker: number; private secondaryMarker: number; private selectedMarkerCount: 0 | 1 | 2 = 0; constructor (data: any, options: L.GeoJSONOptions) { super(); // Set Default Options const defaultOptions = { onEachFeature: this.onEachFeature.bind(this), pointToLayer: this.pointToLayer.bind(this), } as L.GeoJSONOptions; L.Util.setOptions(this, {...defaultOptions, ...options}); // Add data geojson data to the map super.addData(data); } // Do things after this layer is added to the map public onAdd = (map: L.Map): this => { const svg = L.DomUtil.create('svg', 'leaflet-zoom-animated crocodile') as unknown as SVGElement; const originProp = L.DomUtil.testProp(['transformOrigin', 'WebkitTransformOrigin', 'msTransformOrigin']); if (originProp) { svg.style[originProp] = '50% 50%'; svg.setAttribute('width', '1000'); svg.setAttribute('height', '1000'); } const svgOverlay = new L.SVGOverlay(svg, map.getBounds()) svgOverlay.addTo(map); animatedBezier(svg); return super.onAdd(map); } // Place Feature on Map TODO: Remove generalize and remove reference to Facility, inbound, outbound, internal. public pointToLayer = (geoJsonPoint: Feature, latLng: L.LatLng) => { const pieData = Object.keys(geoJsonPoint.properties.pieData).map((segmentName: 'inbound'| 'outbound' | 'internal') => { const label = segmentName; const segment = geoJsonPoint.properties.pieData[label]; let color = '#FFFFFF'; switch(segmentName) { case 'inbound': color = '#FD9108'; break; case 'outbound': color = '#00A1EE' break; case 'internal': color = '#BA58E1' break; } return new ArcData(segment.val, segmentName, color) }); const pieIcon = new PieMarker({ radius: 30, shadow: { xOffset: 0, yOffset: 0, standardDeviation: 0 } }, pieData); return new L.Marker(latLng, { icon: pieIcon }); } // Feature Initialization public onEachFeature = (feature: Feature, layer: L.Layer) => { layer.on('click', this.handleFeatureClicked, this); layer.on('mouseover', this.handleFeatureMouseOver, this); layer.on('mouseout', this.handleFeatureMouseOut, this); // layer.bindPopup(feature.properties.facilityName); } private handleFeatureClicked = (e: L.LeafletEvent) => { const targetItem = e.target.feature.properties.origin_id; // If features are selected } private handleFeatureMouseOver = (e: L.LeafletEvent) => { const targetItem = e.target.feature.properties.origin_id; switch(this.selectedMarkerCount) { case 0: { this.primaryMarker = targetItem; const line = new BezierCurve(new L.Point(100, 100), new L.Point(0, 0), {animate: true, className: 'turtle'}); line.addTo(this._map); break; } case 1: { this.secondaryMarker = targetItem; break; } case 2: { // Do Nothing. break; } default: { console.error(`Impossible Marker count received ${this.selectedMarkerCount}`) } } } private handleFeatureMouseOut = (e: L.LeafletEvent) => { switch(this.selectedMarkerCount) { case 0: { this.primaryMarker = null; break; } case 1: { this.secondaryMarker = null; break; } case 2: { // Do Nothing. break; } default: { console.error(`Impossible Marker count received ${this.selectedMarkerCount}`) } } } }