Skip to content

Enable drawing mode

Bart van 't Ende edited this page Jan 22, 2015 · 2 revisions

Before starting this tutorial, I recommend going through the Enable edit mode page, as this is required for the drawing mode to work.

Please note that this feature is still in development.

The files used for csMap are located in the Development-edit branch and the files for csWeb in the Development branch.

We need to make changes to both csWeb and csMap in order to enable this functionality. Please follow these steps:

csWeb

Copy files

1 The following files have been changed for this feature, please copy them:

  • directives/FeatureTypes/FeatureTypes.tpl.html
  • directives/FeatureTypes/FeatureTypesCtrl.ts
  • directives/PropertyTypes/PropertyTypes.tpl.html
  • directives/PropertyTypes/PropertyTypesCtrl.ts
  • directives/LayersList/LayersDirective.tpl.html
  • directives/LayersList/LayersDirectiveCtrl.ts

MapCtrl

1 Add the interface IDrawTypes

javascript export interface IDrawTypes { name : string; drawingMode : string; iconUri : string; description : string; }


2 Add these variables in the IMapLayersScope

```javascript
drawItems: IDrawTypes[];
selectedFeatureLayer: string;
initDrawMode: boolean;

3 Add these dependencies in the $inject variable

'messageBusService',
'layerService'

4 And add this in the constructor of the class

private $messageBusService  : csComp.Services.MessageBusService,
private $layerService       : csComp.Services.LayerService

and

$scope.selectedFeatureLayer = '';
$scope.initDrawMode = false;

this.$messageBusService.subscribe("drawmode", this.drawModeMessageReceived);

5 Finally add these methods to finish the MapCtrl.ts

        /**
         * Enables of disables the Leaflet.Draw toolbar depending on the received message
         */
        private drawModeMessageReceived = (title: string): void => {
            if (!this.$scope.initDrawMode) {
                // Get all the features
                var drawTypes = this.updateDrawTypes();
                // Add the items to the (current) map layer
                this.$mapService.initDrawableMap(drawTypes);
                this.$scope.initDrawMode = true;
            }
            if (title !== '') {
                if (this.$scope.selectedFeatureLayer != '' && title != this.$scope.selectedFeatureLayer) {
                    // Remove the Leaflet.Draw from the layer if it exists
                    this.$mapService.disableDrawableMap();
                }
                // Show the Leaflet.Draw toolbar
                this.$mapService.enableDrawableMap(drawTypes);
            } else {
                // Remove the Leaflet.Draw toolbar
                this.$mapService.disableDrawableMap();
            }

            this.$scope.selectedFeatureLayer = title;

            // NOTE EV: You need to call apply only when an event is received outside the angular scope.
            // However, make sure you are not calling this inside an angular apply cycle, as it will generate an error.
            if (this.$scope.$root.$$phase != '$apply' && this.$scope.$root.$$phase != '$digest') {
                this.$scope.$apply();
            }
        }
        
        private updateDrawTypes() {
            var drawItems: Array<IDrawTypes> = [];
            var existingItems: Array<String> = [];
            for (var key in this.$layerService.featureTypes) {
                var ft = this.$layerService.featureTypes[key];
                var name        = this.getName(key, ft);
                var drawingMode = ft.style.drawingMode;
                var iconUri     = this.getImageUri(ft);
                var description = 'Klik op het icoon om een nieuw ' + name + ' aan te maken.';
                this.injectIconCSS(name, iconUri);
                var existingItem = name;
                if (existingItems.indexOf(existingItem) < 0) {
                    existingItems.push(existingItem);
                    drawItems.push({
                        "name": name,
                        "drawingMode": drawingMode,
                        "iconUri": iconUri,
                        "description": description
                    });
                }
            }
            drawItems.sort((a: IDrawTypes, b: IDrawTypes) => {
                if (a.name > b.name) return 1;
                if (a.name < b.name) return -1;
                return 0;
            });
            return drawItems;
        }

        private getImageUri(ft: csComp.Services.IFeatureType): string {
            if (ft.style != null && ft.style.drawingMode != null && ft.style.drawingMode.toLowerCase() != "point") {
                if (ft.style.iconUri && ft.style.iconUri.indexOf('_Media') < 0)
                    return ft.style.iconUri;
                else
                    return "includes/images/polygon.png";
            }
            else if (ft.style != null && ft.style.iconUri != null) {
                return ft.style.iconUri;
            }
            else {
                return "includes/images/marker.png";
            }
        }

        private getName(key: string, ft: csComp.Services.IFeatureType): string {
            if (ft.name != null) {
                return ft.name;
            }
            else {
                return key;
            }
        }

        private injectIconCSS(name, iconUri) {
            var t = "{\"." + name.replace(/\s+/g, '-').toLowerCase() + "\":";
            if (iconUri != null) {
                t += " { \"background-image\": \"url('" + iconUri + "') !important\",";
            };
            t += " \"background-size\": \"20px 20px\",\"background-color\": \"#fff !important\",\"border-style\": \"none\"} }";
            var json = $.parseJSON(t);
            (<any>$).injectCSS(json);
        }

MapService

1 Add the following variables to MapService.ts

private drawControl: any;
private drawnItems: any;

2 Add the following code to MapService.ts

        /**
         * Generates the Leaflet.Draw toolbar with the features
         */
        public initDrawableMap(drawTypes) {
            this.drawnItems = L.featureGroup().addTo(this.map);

            // Generate the ModeHandlers for the features
            this.setModeHandlers(drawTypes);

            // Draws the control panel object
            this.drawControl = new (<any>L).Control.Draw({
                edit: { featureGroup: this.drawnItems },
                position: 'bottomleft'
            });

            // Listener for when a item gets created
            this.map.on('draw:created', function (event) {
                this.saveDrawnItem(event);
                console.log(event);
            }.bind(this));
        }

        /**
         * Shows the Leaflet.Draw toolbar
         */
        public enableDrawableMap(drawTypes) {
            this.map.addControl(this.drawControl);            
        }

        /**
         * Disables the Leaflet.Draw toolbar
         */
        public disableDrawableMap() {
            this.map.removeControl(this.drawControl);
        }

        /**
         * Gets called upon when an item gets drawed by the user
         */
        public saveDrawnItem(item) {
            var layer = item.layer;
            var type = item.layerType;

            this.drawnItems.addLayer(layer);
            
            // TODO: Identify item and save values
            
            // TODO: Open sidebar with available properties

        }

        /**
         * Overwrite the default Leaflet.Draw mode handlers with the features mode handlers
         */
        public setModeHandlers(drawTypes) {
            (<any>L).DrawToolbar.include({
                getModeHandlers: function (map) {
                    var modeHandlers = [];

                    for (feature in drawTypes) {
                        var feature = drawTypes[feature];
                        var drawingMode = undefined;
                        
                        // Add more drawing types here when they become available
                        switch (feature.drawingMode) {
                            case ('Point'):
                                drawingMode = new (<any>L).Draw.Marker(map);
                                break;
                            case ('Polygon'):
                                drawingMode = new (<any>L).Draw.Polygon(map);
                                break;
                        }

                        var modeHandler = {
                            enabled: true,
                            handler: drawingMode,
                            title: feature.description,
                            name: feature.name
                        }
                        modeHandlers.push(modeHandler);
                    }
                    return modeHandlers;
                }
            });            
        }

Recompile the project

Don't forget to recompile the project with Visual Studio!

csMap

bower.json

1 Add the following code to bower.json under "dependencies"

"leaflet-draw": "~0.2.3"

index.html

2 Add the following code to index.html

<link href="bower_components/leaflet-draw/dist/leaflet.draw.css" rel="stylesheet" />

<script src="js/cs/leaflet.draw.js"></script>

style.css

3 Add the following code to css/style.css

.selectedFeature {
    color: #0097cf;
}

leaflet.draw.js

4 Add the js/cs/leaflet.draw.js file to your project

Bower update

5 In order to wrap things up in csMap you need to run bower install in your terminal