Ticket #1986 (closed bug: fixed)
Vector features are not correclty ordered (Z-Index) when a feature is part visible
| Reported by: | openlayers | Owned by: | ahocevar |
|---|---|---|---|
| Priority: | minor | Milestone: | 2.8 Release |
| Component: | Renderer.Elements | Version: | 2.7 |
| Keywords: | Cc: | adam.borrows@… | |
| State: | Complete |
Description
Observed using IE7 to view pages hosted on IIS5.
To reproduce: Create a vector layer with a mixture of overlapping vector features, e.g. points on a line (I used KML) so that the line is rendered before the points. Now force the points to sit above the line, using style.graphicZIndex, you'll also need to set the zIndexing render option for the layer. Finally you need some way to force a redraw of the line, in our real app this happens when a user clicks on the line to display a message bubble. OK... Zoom/scroll the map so you can see the whole line, and force a redraw, the line will be correctly displayed under the points. Now zoom/scroll so that the points rendered first (and part of the line) are off the map window. Again force a redraw the line is incorrectly drawn above the points.
Solution: The bug is located in OpenLayers.ElementsIndexer.insert there is a line:
return nextIndex < this.order.length ?
OpenLayers.Util.getElement(this.order[nextIndex]) : null;
This should return the element related to the next note in the order stack, then cascade up redrawing each overlapping element. If the next element is not in the map window then OpenLayers.Util.getElement returns null or undefined, not initially a problem as if the element is not visible there is no need to redraw it. However, this then stops the cascade up the stack, preventing elements further up the stack (that may be visible) being redrawn. The code needs to continue up the order stack even if not all the elements are being redrawn. The above should be replaced by:
return this.getNextElement(rightIndex);
and the following function added to OpenLayers.ElementsIndexer:
getNextElement: function(index) {
var nextIndex = index + 1;
if (nextIndex < this.order.length){
var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
if (nextElement == undefined){
nextElement = this.getNextElement(nextIndex);
}
return nextElement;
} else {
return null;
}
},

