1 | /* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
---|
2 | * full list of contributors). Published under the Clear BSD license. |
---|
3 | * See http://svn.openlayers.org/trunk/openlayers/license.txt for the |
---|
4 | * full text of the license. */ |
---|
5 | |
---|
6 | /** |
---|
7 | * Class: OpenLayers.Renderer |
---|
8 | * This is the base class for all renderers. |
---|
9 | * |
---|
10 | * This is based on a merger code written by Paul Spencer and Bertil Chapuis. |
---|
11 | * It is largely composed of virtual functions that are to be implemented |
---|
12 | * in technology-specific subclasses, but there is some generic code too. |
---|
13 | * |
---|
14 | * The functions that *are* implemented here merely deal with the maintenance |
---|
15 | * of the size and extent variables, as well as the cached 'resolution' |
---|
16 | * value. |
---|
17 | * |
---|
18 | * A note to the user that all subclasses should use getResolution() instead |
---|
19 | * of directly accessing this.resolution in order to correctly use the |
---|
20 | * cacheing system. |
---|
21 | * |
---|
22 | */ |
---|
23 | OpenLayers.Renderer = OpenLayers.Class({ |
---|
24 | |
---|
25 | /** |
---|
26 | * Property: container |
---|
27 | * {DOMElement} |
---|
28 | */ |
---|
29 | container: null, |
---|
30 | |
---|
31 | /** |
---|
32 | * Property: root |
---|
33 | * {DOMElement} |
---|
34 | */ |
---|
35 | root: null, |
---|
36 | |
---|
37 | /** |
---|
38 | * Property: extent |
---|
39 | * {<OpenLayers.Bounds>} |
---|
40 | */ |
---|
41 | extent: null, |
---|
42 | |
---|
43 | /** |
---|
44 | * Property: locked |
---|
45 | * {Boolean} If the renderer is currently in a state where many things |
---|
46 | * are changing, the 'locked' property is set to true. This means |
---|
47 | * that renderers can expect at least one more drawFeature event to be |
---|
48 | * called with the 'locked' property set to 'true': In some renderers, |
---|
49 | * this might make sense to use as a 'only update local information' |
---|
50 | * flag. |
---|
51 | */ |
---|
52 | locked: false, |
---|
53 | |
---|
54 | /** |
---|
55 | * Property: size |
---|
56 | * {<OpenLayers.Size>} |
---|
57 | */ |
---|
58 | size: null, |
---|
59 | |
---|
60 | /** |
---|
61 | * Property: resolution |
---|
62 | * {Float} cache of current map resolution |
---|
63 | */ |
---|
64 | resolution: null, |
---|
65 | |
---|
66 | /** |
---|
67 | * Property: map |
---|
68 | * {<OpenLayers.Map>} Reference to the map -- this is set in Vector's setMap() |
---|
69 | */ |
---|
70 | map: null, |
---|
71 | |
---|
72 | /** |
---|
73 | * Constructor: OpenLayers.Renderer |
---|
74 | * |
---|
75 | * Parameters: |
---|
76 | * containerID - {<String>} |
---|
77 | * options - {Object} options for this renderer. See sublcasses for |
---|
78 | * supported options. |
---|
79 | */ |
---|
80 | initialize: function(containerID, options) { |
---|
81 | this.container = OpenLayers.Util.getElement(containerID); |
---|
82 | }, |
---|
83 | |
---|
84 | /** |
---|
85 | * APIMethod: destroy |
---|
86 | */ |
---|
87 | destroy: function() { |
---|
88 | this.container = null; |
---|
89 | this.extent = null; |
---|
90 | this.size = null; |
---|
91 | this.resolution = null; |
---|
92 | this.map = null; |
---|
93 | }, |
---|
94 | |
---|
95 | /** |
---|
96 | * APIMethod: supported |
---|
97 | * This should be overridden by specific subclasses |
---|
98 | * |
---|
99 | * Returns: |
---|
100 | * {Boolean} Whether or not the browser supports the renderer class |
---|
101 | */ |
---|
102 | supported: function() { |
---|
103 | return false; |
---|
104 | }, |
---|
105 | |
---|
106 | /** |
---|
107 | * Method: setExtent |
---|
108 | * Set the visible part of the layer. |
---|
109 | * |
---|
110 | * Resolution has probably changed, so we nullify the resolution |
---|
111 | * cache (this.resolution) -- this way it will be re-computed when |
---|
112 | * next it is needed. |
---|
113 | * We nullify the resolution cache (this.resolution) if resolutionChanged |
---|
114 | * is set to true - this way it will be re-computed on the next |
---|
115 | * getResolution() request. |
---|
116 | * |
---|
117 | * Parameters: |
---|
118 | * extent - {<OpenLayers.Bounds>} |
---|
119 | * resolutionChanged - {Boolean} |
---|
120 | */ |
---|
121 | setExtent: function(extent, resolutionChanged) { |
---|
122 | this.extent = extent.clone(); |
---|
123 | if (resolutionChanged) { |
---|
124 | this.resolution = null; |
---|
125 | } |
---|
126 | }, |
---|
127 | |
---|
128 | /** |
---|
129 | * Method: setSize |
---|
130 | * Sets the size of the drawing surface. |
---|
131 | * |
---|
132 | * Resolution has probably changed, so we nullify the resolution |
---|
133 | * cache (this.resolution) -- this way it will be re-computed when |
---|
134 | * next it is needed. |
---|
135 | * |
---|
136 | * Parameters: |
---|
137 | * size - {<OpenLayers.Size>} |
---|
138 | */ |
---|
139 | setSize: function(size) { |
---|
140 | this.size = size.clone(); |
---|
141 | this.resolution = null; |
---|
142 | }, |
---|
143 | |
---|
144 | /** |
---|
145 | * Method: getResolution |
---|
146 | * Uses cached copy of resolution if available to minimize computing |
---|
147 | * |
---|
148 | * Returns: |
---|
149 | * The current map's resolution |
---|
150 | */ |
---|
151 | getResolution: function() { |
---|
152 | this.resolution = this.resolution || this.map.getResolution(); |
---|
153 | return this.resolution; |
---|
154 | }, |
---|
155 | |
---|
156 | /** |
---|
157 | * Method: drawFeature |
---|
158 | * Draw the feature. The optional style argument can be used |
---|
159 | * to override the feature's own style. This method should only |
---|
160 | * be called from layer.drawFeature(). |
---|
161 | * |
---|
162 | * Parameters: |
---|
163 | * feature - {<OpenLayers.Feature.Vector>} |
---|
164 | * style - {<Object>} |
---|
165 | * |
---|
166 | * Returns: |
---|
167 | * {Boolean} true if the feature has been drawn completely, false if not, |
---|
168 | * undefined if the feature had no geometry |
---|
169 | */ |
---|
170 | drawFeature: function(feature, style) { |
---|
171 | if(style == null) { |
---|
172 | style = feature.style; |
---|
173 | } |
---|
174 | if (feature.geometry) { |
---|
175 | var bounds = feature.geometry.getBounds(); |
---|
176 | if(bounds) { |
---|
177 | if (!bounds.intersectsBounds(this.extent)) { |
---|
178 | style = {display: "none"}; |
---|
179 | } |
---|
180 | var rendered = this.drawGeometry(feature.geometry, style, feature.id); |
---|
181 | if(style.display != "none" && style.label && rendered !== false) { |
---|
182 | var location = feature.geometry.getCentroid(); |
---|
183 | if(style.labelXOffset || style.labelYOffset) { |
---|
184 | xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset; |
---|
185 | yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset; |
---|
186 | var res = this.getResolution(); |
---|
187 | location.move(xOffset*res, yOffset*res); |
---|
188 | } |
---|
189 | this.drawText(feature.id, style, location); |
---|
190 | } else { |
---|
191 | this.removeText(feature.id); |
---|
192 | } |
---|
193 | return rendered; |
---|
194 | } |
---|
195 | } |
---|
196 | }, |
---|
197 | |
---|
198 | |
---|
199 | /** |
---|
200 | * Method: drawGeometry |
---|
201 | * |
---|
202 | * Draw a geometry. This should only be called from the renderer itself. |
---|
203 | * Use layer.drawFeature() from outside the renderer. |
---|
204 | * virtual function |
---|
205 | * |
---|
206 | * Parameters: |
---|
207 | * geometry - {<OpenLayers.Geometry>} |
---|
208 | * style - {Object} |
---|
209 | * featureId - {<String>} |
---|
210 | */ |
---|
211 | drawGeometry: function(geometry, style, featureId) {}, |
---|
212 | |
---|
213 | /** |
---|
214 | * Method: drawText |
---|
215 | * Function for drawing text labels. |
---|
216 | * This method is only called by the renderer itself. |
---|
217 | * |
---|
218 | * Parameters: |
---|
219 | * featureId - {String} |
---|
220 | * style - |
---|
221 | * location - {<OpenLayers.Geometry.Point>} |
---|
222 | */ |
---|
223 | drawText: function(featureId, style, location) {}, |
---|
224 | |
---|
225 | /** |
---|
226 | * Method: removeText |
---|
227 | * Function for removing text labels. |
---|
228 | * This method is only called by the renderer itself. |
---|
229 | * |
---|
230 | * Parameters: |
---|
231 | * featureId - {String} |
---|
232 | */ |
---|
233 | removeText: function(featureId) {}, |
---|
234 | |
---|
235 | /** |
---|
236 | * Method: clear |
---|
237 | * Clear all vectors from the renderer. |
---|
238 | * virtual function. |
---|
239 | */ |
---|
240 | clear: function() {}, |
---|
241 | |
---|
242 | /** |
---|
243 | * Method: getFeatureIdFromEvent |
---|
244 | * Returns a feature id from an event on the renderer. |
---|
245 | * How this happens is specific to the renderer. This should be |
---|
246 | * called from layer.getFeatureFromEvent(). |
---|
247 | * Virtual function. |
---|
248 | * |
---|
249 | * Parameters: |
---|
250 | * evt - {<OpenLayers.Event>} |
---|
251 | * |
---|
252 | * Returns: |
---|
253 | * {String} A feature id or null. |
---|
254 | */ |
---|
255 | getFeatureIdFromEvent: function(evt) {}, |
---|
256 | |
---|
257 | /** |
---|
258 | * Method: eraseFeatures |
---|
259 | * This is called by the layer to erase features |
---|
260 | * |
---|
261 | * Parameters: |
---|
262 | * features - {Array(<OpenLayers.Feature.Vector>)} |
---|
263 | */ |
---|
264 | eraseFeatures: function(features) { |
---|
265 | if(!(features instanceof Array)) { |
---|
266 | features = [features]; |
---|
267 | } |
---|
268 | for(var i=0, len=features.length; i<len; ++i) { |
---|
269 | var feature = features[i]; |
---|
270 | this.eraseGeometry(feature.geometry, feature.id); |
---|
271 | this.removeText(feature.id); |
---|
272 | } |
---|
273 | }, |
---|
274 | |
---|
275 | /** |
---|
276 | * Method: eraseGeometry |
---|
277 | * Remove a geometry from the renderer (by id). |
---|
278 | * virtual function. |
---|
279 | * |
---|
280 | * Parameters: |
---|
281 | * geometry - {<OpenLayers.Geometry>} |
---|
282 | * featureId - {String} |
---|
283 | */ |
---|
284 | eraseGeometry: function(geometry, featureId) {}, |
---|
285 | |
---|
286 | /** |
---|
287 | * Method: moveRoot |
---|
288 | * moves this renderer's root to a (different) renderer. |
---|
289 | * To be implemented by subclasses that require a common renderer root for |
---|
290 | * feature selection. |
---|
291 | * |
---|
292 | * Parameters: |
---|
293 | * renderer - {<OpenLayers.Renderer>} target renderer for the moved root |
---|
294 | */ |
---|
295 | moveRoot: function(renderer) {}, |
---|
296 | |
---|
297 | /** |
---|
298 | * Method: getRenderLayerId |
---|
299 | * Gets the layer that this renderer's output appears on. If moveRoot was |
---|
300 | * used, this will be different from the id of the layer containing the |
---|
301 | * features rendered by this renderer. |
---|
302 | * |
---|
303 | * Returns: |
---|
304 | * {String} the id of the output layer. |
---|
305 | */ |
---|
306 | getRenderLayerId: function() { |
---|
307 | return this.container.id; |
---|
308 | }, |
---|
309 | |
---|
310 | /** |
---|
311 | * Method: applyDefaultSymbolizer |
---|
312 | * |
---|
313 | * Parameters: |
---|
314 | * symbolizer - {Object} |
---|
315 | * |
---|
316 | * Returns: |
---|
317 | * {Object} |
---|
318 | */ |
---|
319 | applyDefaultSymbolizer: function(symbolizer) { |
---|
320 | var result = OpenLayers.Util.extend({}, |
---|
321 | OpenLayers.Renderer.defaultSymbolizer); |
---|
322 | if(symbolizer.stroke === false) { |
---|
323 | delete result.strokeWidth; |
---|
324 | delete result.strokeColor; |
---|
325 | } |
---|
326 | if(symbolizer.fill === false) { |
---|
327 | delete result.fillColor; |
---|
328 | } |
---|
329 | OpenLayers.Util.extend(result, symbolizer); |
---|
330 | return result; |
---|
331 | }, |
---|
332 | |
---|
333 | CLASS_NAME: "OpenLayers.Renderer" |
---|
334 | }); |
---|
335 | |
---|
336 | /** |
---|
337 | * Constant: OpenLayers.Renderer.defaultSymbolizer |
---|
338 | * {Object} Properties from this symbolizer will be applied to symbolizers |
---|
339 | * with missing properties. This can also be used to set a global |
---|
340 | * symbolizer default in OpenLayers. To be SLD 1.x compliant, add the |
---|
341 | * following code before rendering any vector features: |
---|
342 | * (code) |
---|
343 | * OpenLayers.Renderer.defaultSymbolizer = { |
---|
344 | * fillColor: "#808080", |
---|
345 | * fillOpacity: 1, |
---|
346 | * strokeColor: "#000000", |
---|
347 | * strokeOpacity: 1, |
---|
348 | * strokeWidth: 1, |
---|
349 | * pointRadius: 3, |
---|
350 | * graphicName: "square" |
---|
351 | * }; |
---|
352 | * (end) |
---|
353 | */ |
---|
354 | OpenLayers.Renderer.defaultSymbolizer = { |
---|
355 | fillColor: "#000000", |
---|
356 | strokeColor: "#000000", |
---|
357 | strokeWidth: 2, |
---|
358 | fillOpacity: 1, |
---|
359 | strokeOpacity: 1, |
---|
360 | pointRadius: 0 |
---|
361 | }; |
---|
362 | |
---|