Search code examples
openlayersopenlayers-3

How to set limit to radius of drawing circle in openlayers?


I want to set max radius option to ol.interaction.draw (type of Circle). But i couldn't find any option that offically added.

I can handle "drawend" event and cancel it manually if radius exceed over limit. But it's not exactly what i want. if you reach the limit of radius, drawing event shouldn't be end.The drawn circle should stop expanding instead. User can keep changing radius by draw interaction until clicks 2nd time (user may draw it lower again in the mean time).

Hope i explained my problem well enough.

openlayer v3


Solution

  • You can use a geometry function to where the custom geometry it produces is a circle with a maximum radius

    <!doctype html>
    <html lang="en">
      <head>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.7.0/css/ol.css" type="text/css">
        <style>
          html, body, .map {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
          }
          #map {
            position: relative;
          }
          #form {
            z-index: 1;
            opacity: 1;
            position: absolute;
            bottom: 0;
            left: 0;
            margin: 0;
          }
        </style>
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.7.0/build/ol.js"></script>
      </head>
      <body>
        <div id="map" class="map"></div>
        <form id="form">
        <label>
          Max radius
          <input id="slider" type="range" min="1" max="200" value="100" />
          +<span id="output"></span> meters
        </label>
        </form>
        <script type="text/javascript">
    
    const raster = new ol.layer.Tile({
      source: new ol.source.OSM()
    });
    
    const source = new ol.source.Vector({ wrapX: false });
    
    const vector = new ol.layer.Vector({
      source: source
    });
    
    const map = new ol.Map({
      layers: [raster, vector],
      target: "map",
      view: new ol.View({
        center: [-11000000, 4600000],
        zoom: 4
      })
    });
    
    const slider = document.getElementById("slider");
    const output = document.getElementById("output");
    const scale = 5000;
    slider.addEventListener("input", function () {
      output.innerText = slider.value * scale;
    });
    output.innerText = slider.value * scale;
    
    const draw = new ol.interaction.Draw({
      source: source,
      type: 'Circle',
      geometryFunction: function (coordinates, geometry) {
        const center = coordinates[0];
        const last = coordinates[coordinates.length - 1];
        const dx = center[0] - last[0];
        const dy = center[1] - last[1];
        const maxRadius = slider.value * scale;
        const radius = Math.min(Math.sqrt(dx * dx + dy * dy), maxRadius);
        if (!geometry) {
          geometry = new ol.geom.Circle(center, radius);
        } else {
          geometry.setCenterAndRadius(center, radius);
        }
        return geometry;
      }
    });
    map.addInteraction(draw);
    
        </script>
      </body>
    </html>