woensdag 23 juni 2010

Anchor Renderer

So as I wrote in an earlier post, for the GEOZET viewer the features in the map need to be accessible by keyboard, that's why we ended up using anchors. The anchors are styled using a css class coming from a feature attribute.

So the HTML I had to create using the renderer is for the normal features an anchor with a css class to map to the background-image, the anchor is absolutely positioned. The innerHTML of the anchor has the internal id used also in the print list, it won't be visible in the map only when printing. The identifiers (id attributes) of the anchors are the feature ids generated by OpenLayers. Since background-image print can be troublesome, we decided to print white blocks with the number in it, corresponding to a number in a list underneath the map. Using only border color to differentiate the feature classes.

For clusters we needed a different HTML structure, since the number of features present in the cluster needed to be displayed. It is an anchor with a span, the span contains the internal ID. The anchor also has a child of type "strong" with the number of features in the cluster in it. This is used as the label.

The first issue I ran into was that all renderers coupled to an OpenLayers.Layer.Vector needed to be in the OpenLayers namespace, which is the subject of:

http://trac.openlayers.org/ticket/2669

I had some trouble deciding whether or not my custom renderer needed to extend OpenLayers.Renderer.Elements or OpenLayers.Renderer. In the end I decided on the latter, mostly since the only overlap was the getFeatureIdFromEvent function, and also since I needed to put an _style object on all the nodes to overcome destroy issues in IE.

The drawText function is used to add labels for the cluster features, and it looks something like:


Since I incrementally implemented my Renderer, I had a few situations in which strange things were happening, for instance using the cluster strategy, I was getting more and more features on my map, until I realized that I had not yet implemented eraseGeometry in my Renderer. One of the problems I had when implementing the renderer is the fact that eraseGeometry does not get the featureId, and I needed to get easy access to the DOM structure associated with the feature, using the featureId and not the geometry id. This is subject of:

http://trac.openlayers.org/ticket/2693

Chris Schmidt already answered on the e-mail list that he has no objection to this change. This would also be a benefit for the existing Canvas Renderer of OpenLayers, since it does not need to keep a node hashmap mapping featureIds to geometryIds anymore.

My implementation of eraseGeometry ended up to be very simple:


I did not need to implement removeText, since in my Renderer the labels are part of the DOM structure of the feature, so it will automatically be cleared when the geometry is erased.

The drawGeometry function ended up to be the most difficult. It took some time for me to realize that if the style object passed has a display property of "none", that the Renderer should not draw the feature, or even remove it from the DOM if it exists. The current code is something like (this still needs to be cleaned up so bear with me):


Goes to say lastly that this Renderer only supports point geometries. This could be a start to replace the Marker layer maybe in the future, I am not sure.

The vector layer definition is now:


Here is a screenshot of the print function (the administrative list with the numbers corresponding to the features in the map follows on page 2, not included in this screendump), we still need to find a way to get a good internal number for the features, maybe by having the Web Feature Service sort them by the distance from the center:


Geen opmerkingen:

Een reactie plaatsen