Thursday 29 March 2018

OpenLayers: Feature edit handles not appearing when addUniqueValueRules applied


I have been pulling my hair out over this issue and am now wondering if it is a bug rather than something I am doing wrong.


The Problem: I have a vector layer that users can edit. Each feature on the vector layer has an attribute called "Status" and I am using a unique values renderer to style the features. The layer can contain point, line, and polygon geometries. I have successfully set the layer styling and features are styled according to their status attribute. However, when a user selects a feature to modify the geometry the editing handles are not displayed which means the user is unable to modify the geometry, but the style clearly changes to the edit style. Here are the relevant parts of my code to create the layer:


// Capture the styles for the default render intents of a Vector layer

var defaultSymboliser = OpenLayers.Util.applyDefaults({}, OpenLayers.Feature.Vector.style["default"]);
var selectSymboliser = OpenLayers.Util.applyDefaults({ strokeColor: "red", fillColor: "blue" }, OpenLayers.Feature.Vector.style["select"]);
var temporarySymboliser = OpenLayers.Util.applyDefaults({ strokeColor: "red", fillColor: "blue" }, OpenLayers.Feature.Vector.style["temporary"]);

var editLayerStyleMap = new OpenLayers.StyleMap(
{
'default': defaultSymboliser,
'select': selectSymboliser,
'temporary': temporarySymboliser
}

);

// Create a symboliser lookup that will be used to stye features in their default intent
var symbolisersLookup = {
'Draft': { fillColor: '#0000ff', fillOpacity: 0.4, strokeColor: '#0000ff', pointRadius: 6 },
'Submitted': { fillColor: '#00ff00', fillOpacity: 0.4, strokeColor: '#00ff00', pointRadius: 6 },
'Review': { fillColor: '#ff0000', fillOpacity: 0.4, strokeColor: '#ff0000', pointRadius: 6 },
'Processed': { fillColor: '#9900ff', fillOpacity: 0.4, strokeColor: '#9900ff', pointRadius: 6 }
};


// Add the symboliser and lookup rules to the StyleMap object, using the default intent
editLayerStyleMap.addUniqueValueRules('default', 'Status', symbolisersLookup);

editLayerRefreshStrategy = new OpenLayers.Strategy.Refresh({force: true});
editLayer = new OpenLayers.Layer.Vector("User Submitted Information", {
strategies: [new OpenLayers.Strategy.BBOX(), editLayerRefreshStrategy],
protocol: new OpenLayers.Protocol.HTTP({
url: "Services/UserSubmittedInformationHandler.ashx",
format: new OpenLayers.Format.GeoJSON()
}),

styleMap: editLayerStyleMap
});
mainMap.addLayer(editLayer);

If I comment out the line:


editLayerStyleMap.addUniqueValueRules('default', 'Status', symbolisersLookup);

Then the features are no longer styled according to their status value but the editing handles do now appear. So, is this an OpenLayers bug or have I not done something important that allows the select render intent to work correctly when a UniqueValueRules is applied?



Answer



I've tried everything I can think of but the behaviour of OpenLayers remains the same. I'm convinced this is a bug so will be logging an issue in the bug tracker.



In the meantime I have managed to implement a work-around, that whilst not ideal, will work until there is a fix for the issue. In the end the solution seems obvious but it took me some time to appreciate that fact! So, put simply I remove the StyleMap in the beforefeaturemodified event handler and then apply it again in the afterfeaturemodified event handler. The following is a very rough example of what I do:


editLayer.events.register("beforefeaturemodified", editLayer, function (event) {
editLayer.styleMap.styles["default"].rules = [];

// In addition it seems that virtual vertices are also not respected, their display property is set to "none"
// so we need to override that here.
modifyControl.virtualStyle.display = 'visible';
});

editLayer.events.register("afterfeaturemodified", editLayer, function(event) {

// Put logic here to save edits, etc

// Reapply the style map
addEditLayerStyleMap();
});

function addEditLayerStyleMap() {
var defaultSymboliser = OpenLayers.Util.applyDefaults({}, OpenLayers.Feature.Vector.style["default"]);
var selectSymboliser = OpenLayers.Util.applyDefaults({ strokeColor: "red", fillColor: "blue" }, OpenLayers.Feature.Vector.style["select"]);
var temporarySymboliser = OpenLayers.Util.applyDefaults({ strokeColor: "red", fillColor: "blue" }, OpenLayers.Feature.Vector.style["temporary"]);


var editLayerStyleMap = new OpenLayers.StyleMap(
{
'default': defaultSymboliser,
'select': selectSymboliser,
'temporary': temporarySymboliser
},
{
extendDefault: false
}

);

var symbolisersLookup = {
'Draft': { fillColor: '#0000ff', fillOpacity: 0.4, strokeColor: '#0000ff', pointRadius: 6 },
'Submitted': { fillColor: '#00ff00', fillOpacity: 0.4, strokeColor: '#00ff00', pointRadius: 6 },
'Review': { fillColor: '#ff0000', fillOpacity: 0.4, strokeColor: '#ff0000', pointRadius: 6 },
'Processed': { fillColor: '#9900ff', fillOpacity: 0.4, strokeColor: '#9900ff', pointRadius: 6 }
};

editLayerStyleMap.addUniqueValueRules('default', 'Status', symbolisersLookup);


// Apply the style map to the edit layer
editLayer.styleMap = editLayerStyleMap;
}

I'm going to have a look at the OpenLayers code to see if I can track down the bug and fix it.




BEGIN EDIT:


the line


modifyControl.virtualStyle.display = 'visible';


only gave me the virtual vertices at begin/end of each line segment, but no vertices in the middle (for inserting new vertices). I disabled the stylemap to find out the default values of the virtualStyle property and replaced the line above through:


modifyControl.virtualStyle = {
cursor : "inherit",
fillColor : "#ee9900",
fillOpacity : 0.3,
fontColor : "#000000",
hoverFillColor : "white",
hoverFillOpacity : 0.8,
hoverPointRadius : 1,

hoverPointUnit : "%",
hoverStrokeColor : "red",
hoverStrokeOpacity : 1,
hoverStrokeWidth : 0.2,
labelAlign : "cm",
labelOutlineColor : "white",
labelOutlineWidth : 3,
pointRadius : 6,
pointerEvents : "visiblePainted",
strokeColor : "#ee9900",

strokeDashstyle : "solid",
strokeLinecap : "round",
strokeOpacity : 0.3,
strokeWidth : 1
}

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...