Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ol.control.EditBar #727

Closed
ngjiajunsg opened this issue Jan 12, 2022 · 37 comments
Closed

ol.control.EditBar #727

ngjiajunsg opened this issue Jan 12, 2022 · 37 comments
Labels

Comments

@ngjiajunsg
Copy link

ngjiajunsg commented Jan 12, 2022

Hi Viglino,

i got some issue when i intergate EditBar with PopupFeature.

  1. the popupfeature keep appear when i drawing
  2. for drawing how to stop the drawing like (https://openlayers.org/en/latest/examples/measure.html) to stop drawing is double click
  3. how to stop the drawing and return back to normal state where i able to select/click feature to display the information
@Viglino
Copy link
Owner

Viglino commented Jan 12, 2022

Hi,

  1. You have to close the PopupFeature on drawstart event (popup.hide() or clear selection)
  2. this is the standard behavior of the tool...
  3. You have to listen to drawend event and de-activate the interaction to stop using it
// Remove popup on drawstart (clear selection)
edit.getInteraction('DrawLine').on('drawstart', function() {
  edit.getInteraction('Select').getFeatures().clear();
});
// Stop drawing on drawend
edit.getInteraction('DrawLine').on('drawend', function() {
  edit.getInteraction('DrawLine').setActive(false);
});

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Jan 13, 2022

Hi Viglino,

i try the below code both

// Remove popup on drawstart (clear selection)
edit.getInteraction('DrawLine').on('drawstart', function() {
edit.getInteraction('Select').getFeatures().clear();
});

popup.hide();

both does not work

    • the PopupFeature still appear with blank information
    • error : Uncaught TypeError: popup.hide is not a function

i notice if integrate with PopupFeature, seem like my drawing point does not work.

@Viglino
Copy link
Owner

Viglino commented Jan 13, 2022

Do you have an online example?

@ngjiajunsg
Copy link
Author

this are the code

<title>ol-ext: Edit bar</title> <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script> <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script> <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script> <script type="text/javascript" src="https://viglino.github.io/ol-ext/dist/ol-ext.js"></script> <script src="https://unpkg.com/elm-pep"></script> <style> .ol-button i { color: inherit; } .ol-notification i { color: #fff; } .ol-popup h1 { font-size: 1em; background-size: 2em; padding-left: 3em; } </style>
<script type="text/javascript"> // Vector layer var vector = new ol.layer.Vector( { source: new ol.source.Vector() }) // The map var map = new ol.Map ({ target: 'map', view: new ol.View ({ zoom: 14, center: ol.proj.fromLonLat([103.8198, 1.3521]), zoom:12 }), layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vector ] }); //EditTool bar var note = new ol.control.Notification(); map.addControl(note) // Add the editbar var select = new ol.interaction.Select({ title: 'Sélection'}); select.set('title', 'Sélection'); var edit = new ol.control.EditBar({ // Translate interaction title / label interactions: { // Use our own interaction > set the title inside Select: select, // Define button title DrawLine: 'Ligne', // Drawregular with label DrawRegular: { title: 'Forme régullière', ptsLabel: 'pts', circleLabel: 'cercle' } }, source: vector.getSource() }); map.addControl(edit); // Add a tooltip var tooltip = new ol.Overlay.Tooltip(); map.addOverlay(tooltip); edit.getInteraction('Select').on('select', function(e){ if (this.getFeatures().getLength()) { tooltip.setInfo('Drag points on features to edit...'); } else tooltip.setInfo(); }); edit.getInteraction('Select').on('change:active', function(e){ tooltip.setInfo(''); }); edit.getInteraction('ModifySelect').on('modifystart', function(e){ if (e.features.length===1) tooltip.setFeature(e.features[0]); }); edit.getInteraction('ModifySelect').on('modifyend', function(e){ tooltip.setFeature(); }); edit.getInteraction('DrawPoint').on('change:active', function(e){ tooltip.setInfo(e.oldValue ? '' : 'Click map to place a point...'); }); edit.getInteraction('DrawLine').on('change:active', function(e){ tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing line...'); }); edit.getInteraction('DrawLine').on('drawend', function() { tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing line...'); edit.getInteraction('DrawLine').setActive(false); }); edit.getInteraction('DrawLine').on('drawstart', function(e){ popup.hide(); tooltip.setFeature(e.feature); tooltip.setInfo('Click to continue drawing line...'); }); edit.getInteraction('DrawPolygon').on('drawstart', function(e){ popup.hide(); tooltip.setFeature(e.feature); tooltip.setInfo('Click to continue drawing shape...'); }); edit.getInteraction('DrawPolygon').on('change:active', function(e){ tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing shape...'); }); edit.getInteraction('DrawPolygon').on('drawend', function() { tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing shape...'); edit.getInteraction('DrawPolygon').setActive(false); }); edit.getInteraction('DrawHole').on('drawstart', function(e){ popup.hide(); tooltip.setFeature(e.feature); tooltip.setInfo('Click to continue drawing hole...'); }); edit.getInteraction('DrawHole').on('change:active', function(e){ tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click polygon to start drawing hole...'); }); edit.getInteraction('DrawHole').on('drawend', function() { tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing shape...'); edit.getInteraction('DrawHole').setActive(false); }); edit.getInteraction('DrawRegular').on('drawstart', function(e){ popup.hide(); tooltip.setFeature(e.feature); tooltip.setInfo('Move and click map to finish drawing...'); }); edit.getInteraction('DrawRegular').on('change:active', function(e){ tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing shape...'); }); edit.getInteraction('DrawRegular').on('drawend', function() { tooltip.setFeature(); tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing shape...'); edit.getInteraction('DrawRegular').setActive(false); }); edit.on('info', function(e){ console.log(e) note.show(' '+e.features.getLength()+' feature(s) selected'); }); var a = ol.proj.fromLonLat([103.830933, 1.250111]); var b = ol.proj.fromLonLat([103.852119, 1.296568]); var c = ol.proj.fromLonLat([103.88469,1.34721]); var iconStyle = new ol.style.Style({ image: new ol.style.Icon({ anchor: [0.5, 256], opacity: 0.75, anchorXUnits: 'fraction', anchorYUnits: 'pixels', src: 'https://i.ibb.co/cQHzRWt/4525058.png', scale: 10 / 128 }) }); var layera = new ol.layer.Vector({ source: new ol.source.Vector({ features: [ new ol.Feature({ geometry: new ol.geom.Point(a), name: 'a' }) ] }) }); layera.setStyle(iconStyle); map.addLayer(layera); console.log('Add a'); var layerb = new ol.layer.Vector({ source: new ol.source.Vector({ features: [ new ol.Feature({ geometry: new ol.geom.Point(b), name: 'b' }) ] }) }); layerb.setStyle(iconStyle); map.addLayer(layerb); var layerc = new ol.layer.Vector({ source: new ol.source.Vector({ features: [ new ol.Feature({ geometry: new ol.geom.Point(c), name: 'c' }) ] }) }); layerc.setStyle(iconStyle); map.addLayer(layerc); //PopupFeature var container = document.getElementById('popup1'); var content = document.getElementById('popup-content'); var target = document.getElementById('map'); var overlay = new ol.Overlay({ element: container, autoPan: true, autoPanAnimation:{ duration:250 } }); map.addOverlay(overlay); map.on('pointermove', function(evt){ content.style.left = evt.pixel[0] + 'px'; content.style.top = (evt.pixel[1] - 50) +'px'; var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature,layer){ return feature; }); if (feature){ let coordinate = evt.coordinate; var name = feature.get('name'); console.log('Name: ' + name); overlay.setPosition([coordinate[0] + (20), coordinate[1]]); } else { content.innerHTML =""; } }); // Select interaction var select = new ol.interaction.Select({ hitTolerance: 5, multi: true, condition: ol.events.condition.singleClick }); map.addInteraction(select); var popup = new ol.Overlay.PopupFeature({ popupClass: 'default anim', select: select, canFix: true, template: { title: function(f) { return f.get('name'); } } }); map.addOverlay (popup); </script>

@Viglino
Copy link
Owner

Viglino commented Jan 13, 2022

Can you create a pen on Codepen?

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Jan 14, 2022

Hi Viglino,

ok i will create a pen . sorry about it

https://codepen.io/ngjiajun/full/wvrRmML

@Viglino
Copy link
Owner

Viglino commented Jan 14, 2022

You have to use the select interaction of the edit bar edit.getInteraction('Select') to handle the popup (ie. show poup when selected).
Otherwise, you have to deactivate the selection when drawing to prevent selection/popup to interfere with the drawing itself.
See line 287 > https://codepen.io/viglino/pen/wvrRYPE

@ngjiajunsg
Copy link
Author

thank Viglino,

some questions on the edit bar.

  1. For features that i create using edit bar, am i able to update the name of the feature? (for example a point and label them or a line to label it)
  2. for any features that are edit, am i able to update/save the information such as the lat, long of the position that i change.

@Viglino
Copy link
Owner

Viglino commented Jan 17, 2022

  1. You can add your own buttons to open a form and edit selected features as well. You can use the [i] button to do that for example.
  2. You can get all interactions in the bar to get informed when a feature is modified and do something (save position).
edit.getInteraction('DrawLine').on('drawstart', (e) => {
  var feature = e.feature;
  // Save the geometry
  var geom = feature.getGeometry()
  ...
})

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Jan 17, 2022

sorry i dont understand the logic on the "You can add your own buttons to open a form and edit selected features as well. You can use the [i] button to do that for example."

also can i check with you, how can i remove icons from the editbar, for example just display only drawline and draw polygon?

@Viglino
Copy link
Owner

Viglino commented Jan 17, 2022

In the exemple click on the info button display a notification:

    edit.on('info', function(e){
      console.log(e)
      note.show('<i class="fa fa-info-circle"></i> '+e.features.getLength()+' feature(s) selected');
    });

You can use it to display a form to change feature attributes;

    edit.on('info', function(e){
      var feature = e.features.item(0); // e.features[0] is a Collection
      if (feature) {
         var label = prompt('label');
         feature.set('label', label);
      }
    });

You can also add your own control to the bar:

var editAttr = new ol.control.Button({
  html: 'E',
  title: "attributes",
  handleClick: function() {
    var f = edit.getInteraction('Select').getFeatures().item(0)
    if (f) {
     var label = prompt('label');
     f.set('label', label);
    }
  }
});
edit.addControl (editAttr);

@ngjiajunsg
Copy link
Author

 edit.on('info', function(e){
      var feature = e.features[0];
      if (feature) {
         var label = prompt('label');
         features.set('label', label);
      }
    });

i try add this code but seem like the var feature = e.features[0]; is undefined

@Viglino
Copy link
Owner

Viglino commented Jan 19, 2022

Ok! e.features is not an array but a Collection, try e.features.item(0) instead 😃

@Viglino
Copy link
Owner

Viglino commented Jan 19, 2022

edit.on('info', function(e){
  var feature = e.features.item(0);
  if (feature) {
     var label = prompt('label');
     feature.set('label', label);
  }
});

@ngjiajunsg
Copy link
Author

Hi Viglino,

can i check with you wonder am i able restrict users to move anything from the map.. example https://codepen.io/viglino/pen/wvrRYPE

i have 3 locations point which i dont want users to move it.. is there any other way?

@Viglino
Copy link
Owner

Viglino commented Jan 19, 2022

The default modify interaction in the edit bar use the selected feature but you can set your own modify interaction on creation.
The ModifyFeature interaction lets you add a filter function decide if the feature has to be modified or not.
See http://viglino.github.io/ol-ext/doc/doc-pages/ol.interaction.ModifyFeature.html
Something like that:

edit = new ol.control.Bar({
  interactions: {
     ModifySelect: new ol.interaction.ModifyFeature({
       filter: function(f) {
         // Test if feature can be modified
         if (isModif(f)) return true;
         else return false;
       }
  }
})

Viglino added a commit that referenced this issue Jan 19, 2022
@Viglino
Copy link
Owner

Viglino commented Jan 19, 2022

I've added a setFilter method to let you change the filter directly:

edit.getInteraction('ModifySelect').setFilter(function(f) {
//edit.getInteraction('ModifySelect', function(f) {
   if (isModif(f)) return true;
   else return false;
})

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Jan 20, 2022

Sorry i dont get it as i implement the

edit.getInteraction('ModifySelect', function(f) {
   if (isModif(f)) return true;
   else return false;
})

but i still able to move the fixed feature

@Viglino
Copy link
Owner

Viglino commented Jan 20, 2022

Sorry setFilter() was missing, the code should be:

edit.getInteraction('ModifySelect').setFilter(function(f) { 
   if (isModif(f)) return true;
   else return false;
})

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Jan 20, 2022

Hi Viglino,

Sorry, seem like now all the features unable to edit/modfiy. even newly created from the editbar

in addition, now i also able to delete alway all the predrawn feature

@ngjiajunsg
Copy link
Author

Hi Viglino,

can check with you if i wish the measurement to remain on the features issit possible? and in addition for circle can i check if i draw with shift and ctrl why it show the area of the circle instead of the radius?

@Viglino
Copy link
Owner

Viglino commented Jan 25, 2022

If you want to add information on feature you have to do it by yourself on drawend event.

While drawing you can check the current drawing and modify the tooltip content.

var regular = edit.getInteraction('DrawRegular');
regular.on('drawing', function(e) {
  // Circle?
  if (e.centered && e.square && regular.getSides()<3) {
    // Calculate Length
    var length = ol.sphere.getDistance( ol.proj.toLonLat(e.startCoordinate), ol.proj.toLonLat(e.coordinate) );
    // set measure
    tooltip.set('measure', tooltip.formatLength(length));
  }
})

@ngjiajunsg
Copy link
Author

Hi Viglino,

Sorry, seem like now all the features unable to edit/modfiy. even newly created from the editbar

in addition, now i also able to delete alway all the predrawn feature

@Viglino
Copy link
Owner

Viglino commented Jan 25, 2022

The edition is controlled by the filter you give.
Try display the test on console to see what's wrong:

edit.getInteraction('ModifySelect').setFilter(function(f) {
   console.log('TEST', f, isModif(f));
   if (isModif(f)) return true;
   else return false;
})

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Feb 4, 2022

Hi Viglino,

i got this error.

Uncaught ReferenceError : isModif is not defined
at ol.interaction.ModifyFeature.filterSplit_
at ol.interaction.ModifyFeature.getClosestFeature (ol-ext.js:22969)

i try put this code in codepen (https://codepen.io/ngjiajun/pen/wvrRmML) still the same

[Uncaught ReferenceError: isModif is not defined
at https://cdpn.io/cpe/boomboom/index.html?editors=1011&key=index.html-4c07c6af-6231-0790-34b3-3a8499428ec5:213]

@ngjiajunsg
Copy link
Author

Hi Viglino,

can i check whether i am able to put the measure label display after measure (https://openlayers.org/en/latest/examples/measure.html)

@Viglino
Copy link
Owner

Viglino commented Feb 4, 2022

You have to define your own filter function (isModif) to test if the feature is modifiable or not...
Return true if the feature is modifiable or `false if not...

@ngjiajunsg
Copy link
Author

If you want to add information on feature you have to do it by yourself on drawend event.

While drawing you can check the current drawing and modify the tooltip content.

var regular = edit.getInteraction('DrawRegular');
regular.on('drawing', function(e) {
  // Circle?
  if (e.centered && e.square && regular.getSides()<3) {
    // Calculate Length
    var length = ol.sphere.getDistance( ol.proj.toLonLat(e.startCoordinate), ol.proj.toLonLat(e.coordinate) );
    // set measure
    tooltip.set('measure', tooltip.formatLength(length));
  }
})

Hi Viglino, can check if i want to display both area and distance together?

issit by adding to the area computation into tooltip.set method?

@ngjiajunsg
Copy link
Author

You have to define your own filter function (isModif) to test if the feature is modifiable or not... Return true if the feature is modifiable or `false if not...

can check issit the isModif function workflow should be like

  1. check the layer issit drawing layer if yes is true else is false?

@Viglino
Copy link
Owner

Viglino commented Feb 10, 2022

  1. You can set what you want in the measure property of the tooltip:
    tooltip.set('measure', 'blabla: ' + length + ' - ' + area);

  2. The filter function in the ModifySelect interaction only get the selected feature.
    You don't have access to the layer at this step.
    You have to store the layer as a feature property when inserted in the layer if you want to retrieve it...

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Feb 24, 2022

Hi Viglino,

can i check whether i am able to put the measure label display after measure (https://openlayers.org/en/latest/examples/measure.html)

how can i set the label display after measure for line, shape and polygon?? issit that i need to

output =  ol.sphere.getDistance( ol.proj.toLonLat(e.startCoordinate), ol.proj.toLonLat(e.coordinate) );
tooltip.innerHTML = tooltip.formatLength(output );
tooltip.setPosition(e.coordinate);

@ngjiajunsg
Copy link
Author

  1. The filter function in the ModifySelect interaction only get the selected feature.
    You don't have access to the layer at this step.
    You have to store the layer as a feature property when inserted in the layer if you want to retrieve it...

do you mean by this

var DrawingLayer = new ol.layer.Vector({
source: new ol.source.Vector({
layer: 'Drawing Layer'
}),
title: "Drawing Layer"
});

@Viglino
Copy link
Owner

Viglino commented Feb 24, 2022

how can i set the label display after measure for line, shape and polygon?? issit that i need to

tooltip.set('measure', any_string_you_want);

@Viglino
Copy link
Owner

Viglino commented Feb 24, 2022

  1. You have to store the layer on the feature when you insert it to get the layer back when you have to know it:
source.on('addfeature', function(f) { 
  f.set('layer', layer) 
});
// then you can get layer's back: f.get('layer')

@ngjiajunsg
Copy link
Author

how can i set the label display after measure for line, shape and polygon?? issit that i need to

tooltip.set('measure', any_string_you_want);

i wish to display the measurement at the end of the drawing

https://ibb.co/S78jcvp

String

https://ibb.co/41bwWzd

Polygon

@ngjiajunsg
Copy link
Author

ngjiajunsg commented Feb 28, 2022

  1. You have to store the layer on the feature when you insert it to get the layer back when you have to know it:
source.on('addfeature', function(f) { 
  f.set('layer', layer) 
});
// then you can get layer's back: f.get('layer')

i understand for my own code i able to store this line of code. but for editbar the drawing how should i add the line of code above for all kinds of drawing

for example

edit.getInteraction('DrawPoint').on('change:active', function(e){
      tooltip.setInfo(e.oldValue ? '' : 'Click map to place a point...');
    });
    edit.getInteraction('DrawLine').on(['change:active','drawend'], function(e){
      tooltip.setFeature();
      tooltip.setInfo(e.oldValue ? '' : 'Click map to start drawing line...');
    });

i not sure where should i put it for point and the same for line and poly and shapes

@Viglino
Copy link
Owner

Viglino commented Feb 28, 2022

i wish to display the measurement at the end of the drawing

The editbar example show you how to display measure while drawing. If you want to display information after drawing, just use a Popup.

i understand for my own code i able to store this line of code. but for editbar the drawing how should i add the line of code above for all kinds of drawing

You said you want to know the layer the feature belong to.

can check issit the isModif function workflow should be like : check the layer issit drawing layer if yes is true else is false?

But there is no link between features and layers with ol (the same feature can be in many layers). So you have to set the layer as an attribute on feature insertion (source.on('addfeature', function(f) { f.set('layer', layer) });) to get it back when needed and test in your isModif function...

@Viglino Viglino closed this as completed Mar 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants