Geometry viewer

View GeoJSON or WKT geometries on a base map

HTML

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css">
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="http://tombatossals.github.io/angular-leaflet-directive/dist/angular-leaflet-directive.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="http://cdn-geoweb.s3.amazonaws.com/terraformer/1.0.4/terraformer.min.js"></script>
<script src="http://cdn-geoweb.s3.amazonaws.com/terraformer-wkt-parser/1.0.0/terraformer-wkt-parser.min.js"></script>
<div ng-app="myapp">
  <div ng-controller="MapController">
    <div class="map-container">
      <leaflet id="map" defaults="map.defaults" geojson="features.geojson" center="map.center"></leaflet>
    </div>
    <div class="form-container">
      <form>
        <textarea rows="8" ng-model="form.text" placeholder="Enter WKT or GeoJSON ..."></textarea>
        <button class="btn btn-danger" ng-click="form.text=''" ng-disabled="form.text.length===0">Clear</button>
        <button ng-if="form.curId==null" class="btn btn-primary" ng-click="addFeature(form.text, form.autoZoom)" ng-disabled="form.text.length===0">Add</button>
        <button ng-if="form.curId!=null" class="btn btn-primary" ng-click="updateFeature(form.text, form.autoZoom, form.curId)" ng-disabled="form.text.length===0">Update</button>
        <button class="btn btn-default" ng-click="zoomToFeatures()">Zoom to fit</button>
        <input type="checkbox" ng-model="form.autoZoom">Auto fit</form>
    </div>
    <div class="feature-container">
      <ul class="list-unstyled">
        <li ng-repeat="f in features.original | orderBy:'id'" title={{f.text}}>
          <input type="checkbox" ng-model="f.visible" ng-change="updateLayers()" ng-disabled="form.curId!=null"> <span class="name">[{{f.id+1}}] {{f.name}}</span>

          <button class="btn btn-info btn-xs" ng-disabled="form.curId!=null || !f.visible"...

CSS

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.map-container {
  bottom: 0;
  left: 0;
  position: absolute;
  right: 300px;
  top: 0;
}

.form-container {
  height: 200px;
  padding: 5px;
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}

.feature-container {
  bottom: 0;
  padding: 5px;
  position: absolute;
  right: 0;
  top: 220px;
  width: 300px;
  overflow-y: auto;
  overflow-x: hidden;
}

.angular-leaflet-map {
  height: 100%;
}

form textarea {
  width: 100%;
}

ul>li {
  padding-bottom: 5px;
  white-space: nowrap;
}

JavaScript

var app = angular.module('myapp', ['leaflet-directive']);

app.controller('MapController', function($scope, $timeout, $window, leafletBoundsHelpers, leafletData) {

  $scope.map = {
    defaults: {},
    center: {
      lat: 0,
      lng: 0,
      zoom: 2
    }
  };

  $scope.form = {
    counter: 0,
    text: '',
    autoZoom: true,
    curId: null
  };

  $scope.features = {
    original: [],
    geojson: {
      data: {
        type: 'FeatureCollection',
        features: []
      },
      options: {
        style: {
          fillColor: 'green',
          weight: 2,
          opacity: 1,
          color: 'black',
          fillOpacity: 0.7
        },
        onEachFeature: function(f, l) {
          $scope.featureGroup.addLayer(l);
        }
      }
    }
  };

  $scope.makeFeature = function(text) {
    try {
      if (text.indexOf('{') < 0) {
        return Terraformer.WKT.parse(text);
      }

      var geoJson = JSON.parse(text);
      Terraformer.WKT.convert(geoJson);
      return geoJson;
    } catch (Exception) {
      return;
    }
  };

  $scope.updateLayers = function() {
    var visibleFeatures = $scope.features.original.filter(function(f) {
      return f.visible;
    });

    $scope.featureGroup = L.featureGroup();
    $scope.features.geojson.data.features = visibleFeatures.map(function(f) {
      return $scope.makeFeature(f.text);
    });
  };

  $scope.validate = function(text) {
    var feature = $scope.makeFeature(text);
    if (!feature) {
      $window.alert('Invalid geometry, try again');
      return;
    }
    return feature;
  };

  $scope.refreshMap = function(zoom) {
    $scope.updateLayers();

    if (zoom) {
      $timeout(function() {
        $scope.zoomToFeatures();
      }, 1000);
    }
  };

  $scope.addFeature = function(text, zoom) {
    var feature = $scope.validate(text);
    $scope.features.original.push({
      id: $scope.form.counter++,
      visible: true,
      text: text,
      name: feature.type || 'Feature'
    });
 ...