0

I have a vector layer which i statically load all the features from the JSON file. What I want to do is to create layers dynamically based on the user input.

The user will choose district code, for example, and when button is clicked it will create the layer and zoom to the specified extent (call the ZoomToParcel function) . I haven't found any example in the docs.

var getDistrict, getTownVal, getQuarterVal; //this is user input (suppose they are dynamic)
var vector = new ol.layer.Vector({
    source: new ol.source.Vector({
    url: 'getjson.json', //loaded on client
    format: new ol.format.GeoJSON()
  }),style:style_simple
 //,extent:ol.proj.transformExtent([...], 'EPSG:4326', 'EPSG:3857') //This should be dynamic
});

var map = new ol.Map({
  target: 'map',
  layers: [roadlayer,vector],
    controls: ol.control.defaults().extend([new ol.control.ScaleLine()]),
    view: new ol.View({
    center: ol.proj.fromLonLat([33.33386, 35.14710]),
    zoom: 14,
    maxZoom: 19
  })
});

function ZoomToParcel(){ //the extent here should be dynamic
  let extent = vector.getExtent() || vector.getSource().getTileGrid().getExtent();
  map.getView().fit(extent,{duration: 1590},map.getSize());
}

HTML:

   <p><input type="text"> District</p>
   <p><input type="text"> Town</p>
   <p><input type="text"> Quarter</p>
   <!-- etc... -->
   <button onclick="ZoomToParcel()" class="btn btn-primary">SEARCH</button>

I log the (e) inside the select event, see the dist_code inside the values_ array:

enter image description here

UPDATE: Mike's answer helped with a bit modification, i make the if statement directly in the style. The filtering works fine, but by default the map should not show any layer (only baselayer).

var style_simple = function (feature, resolution) {

  let featureParcel = feature.get("parcel_nbr")+"";
  let featureDist = feature.get("dist_code")+"";
  if(featureDist == 1) {  //show districts with code 1 
  return new ol.style.Style({
  fill: new ol.style.Fill({
    color: 'khaki'
  }),
   stroke: new ol.style.Stroke({
      color: 'blue',
      width: 2
    }),
    text: new ol.style.Text({
      text: featureParcel,
      font: '13px Calibri,sans-serif',
    fill: new ol.style.Fill({
    color: 'blue'
    })
    })
  });
}
}

As Mike suggested, Instead of re-loading the geojson for each change it is easier to filter the features on that property, in the style function so only the one we are interested in are displayed, and when setting the extent.

The user input is dynamic getDistrict (think of it as a drop down with 5-6 districts)

The point is to be able to update the map when input changes. I am a little confused where i should put the change event and how i can update the style accordingly

0

You will need some way of linking the district code to the geoJSON url, such as a new function getJSON. Then you can create a layer and add it to an existing map. The extent of a vector layer is the extent of all the features in the source which you won't know until it is loaded, so wait for an addfeature event then fit. In OpenLayers 5 size is an option for fit, not a parameter.

var vector = new ol.layer.Vector({
    source: new ol.source.Vector({
        url: getJSON(),
        format: new ol.format.GeoJSON()
    }),
    style: style_simple
});

vector.getSource().on('addfeature', function(){
    map.getView().fit(
        vector.getSource().getExtent(),
        { duration: 1590, size: map.getSize() }
    );
 });

map.addLayer(vector);

You could keep the geojson loaded and filter what is displayed using a style function, e.g. to filter only by district

var vector = new ol.layer.Vector({
  source: new ol.source.Vector({
    url: 'getjson.json',
    format: new ol.format.GeoJSON()
  }),
  style: function(feature) {
    if (feature.get('dist_code') == getDistrict) {
      return style_simple;
    }
    return [];
  }
});

You could also set the extent by filtering features by district:

function ZoomToParcel() {
  let extent = ol.extent.createEmpty();
  vector.getSource().forEachFeature(function(feature) {
    if (feature.get('dist_code') == getDistrict) {
       ol.extent.extend(extent, feature.getGeometry().getExtent());
    }
  });
  map.getView().fit(extent, { duration: 1590, size: map.getSize() });
}
  • Mike, the Json file is loaded on the client, for now, can you show an example for adding layer to a fixed district e.g. 1 – csandreas1 Jun 14 at 11:44
  • How do you get the json file for district 1? – Mike Jun 14 at 11:49
  • The JSON is all the data of a whole city (15 mb). The user will choose from 3 inputs (district, town, quarter) and the layers of that area should be added on the map when button is clicked. So i am not sending parameters to the Geoserver, at the moment – csandreas1 Jun 14 at 11:51
  • You will need to load the whole 15mb and filter the features you want to include. Do the features have properties which associate them to districts, or do have to test if they are within the district boundaries? – Mike Jun 14 at 12:03
  • 1
    When the value of the dropdown changes call changed() for the layer because a value used in its style function has changed codepen.io/anon/pen/ZdpYyy – Mike Jun 18 at 13:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.