Aller au contenu

Exercices Outils dessin

Exercice - Dessin, Modification, Export#

Notre objectif est de créer une interface de dessin de polygone, avec un mode édition, et la possiblité d’exporter/importer nos formes. Nous allons utiliser OpenLayers. Pour Leaflet, ce n’est pas natif, mais c’est le plugin Leaflet Draw

  • Dans une carte OpenLayers
  • Créez une nouvelle couche + source vectorielle, vide
  • Ajoutez une interaction de dessin à la carte
    • ol.interaction.Draw, type Polygon, basée sur notre source
    • map.addInteraction()
  • Ajoutez ensuite deux nouvelles interactions (Modify et Snap), après celle de dessin
  • Remarquez qu’OpenLayers gère déjà une grande partie de comportements (création de point, modification, dessin à main levée, etc.)

Ensuite, pour la partie export :

  • Ajoutez en HTML un bouton pour télécharger (et le CSS associé)

<div id="tools">
    <a id="download" download="features.json">Download</a>
</div>
#tools {
    position: absolute;
    top: 1rem;
    right: 1rem;
}
#tools a {
    display: inline-block;
    padding: 0.5rem;
    background: white;
    cursor: pointer;
}

Nous devons maintenant modifier le href de cet objet lorsque la source change. Pour cela :

  • Ajoutez un événement change sur la source
  • Récupérez les features de la source et convertissez-les en geoJSON
    • source.getFeatures()
    • format.writeFeatures(features)
  • Modifiez le href en créant une URL de données (data URL)
    • download.href = "data:application/json;charset=utf-8," + encodeURIComponent(json);

Pour l’import :

  • Ajoutez une nouvelle interaction (ol.interaction.DragAndDrop), toujours sur la même source
  • Précisez le format attendu (formatConstructors: [ol.format.GeoJSON])

Si l’on souhaite ajouter un contrôle pour activer le dessin, il faut :

  • le créer sous forme de classe
  • l’ajouter à la carte (avec le CSS correspondant)
  • ajouter/supprimer les interactions lors du click

class DrawControl extends ol.control.Control {
  constructor() {
    const button = document.createElement('button');
    button.innerHTML = '&#x2b53';

    const element = document.createElement('div');
    element.className = 'draw-control ol-unselectable ol-control';
    element.appendChild(button);

    super({
      element: element,
    });

    this.active = false;

    button.addEventListener('click', () => this.click());
  }

  click() {
    this.active = !this.active;
    if (this.active) {
        map.addInteraction(modifyInteraction);
        map.addInteraction(drawInteraction);
        map.addInteraction(snapInteraction);
        this.element.classList.add('is-active');
    } else {
        map.removeInteraction(modifyInteraction);
        map.removeInteraction(drawInteraction);
        map.removeInteraction(snapInteraction);
        this.element.classList.remove('is-active');
    }
  }
}

let map = new ol.Map({
    ...
    controls: ol.control.defaults.defaults().extend([
        new DrawControl()
    ])
});
.draw-control {
    top: 65px;
    left: 0.5em;
}
.is-active button,
.is-active button:hover,
.is-active button:focus {
    background: mediumblue;
    color: #fff;
}