Ticket #1433: 1433-r7045-A2.2.patch
| File 1433-r7045-A2.2.patch, 13.0 kB (added by ahocevar, 8 months ago) |
|---|
-
examples/styles-rotation.html
old new 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title>OpenLayers Styles Rotation Example</title> 4 <style type="text/css"> 5 #map { 6 width: 800px; 7 height: 475px; 8 border: 1px solid black; 9 } 10 </style> 11 <script src="../lib/OpenLayers.js" type="text/javascript"></script> 12 <script type="text/javascript"> 13 14 var map; 15 var vectors; 16 17 function init(){ 18 map = new OpenLayers.Map('map'); 19 var wms = new OpenLayers.Layer.WMS( 20 "OpenLayers WMS", 21 "http://labs.metacarta.com/wms/vmap0", 22 {layers: 'basic'} 23 ); 24 25 vectors = new OpenLayers.Layer.Vector( 26 "Simple Geometry", 27 { 28 styleMap: new OpenLayers.StyleMap({ 29 "default": { 30 externalGraphic: "../img/marker-gold.png", 31 //graphicWidth: 17, 32 graphicHeight: 20, 33 graphicYOffset: -19, 34 rotation: "${angle}", 35 fillOpacity: "${opacity}" 36 }, 37 "select": { 38 cursor: "crosshair", 39 externalGraphic: "../img/marker.png" 40 } 41 }) 42 } 43 ); 44 45 map.addLayers([wms, vectors]); 46 47 var features = []; 48 var x = -111.04; 49 var y = 45.68; 50 for(var i = 0; i < 10; i++){ 51 x += i * .5; 52 y += i * .1; 53 features.push( 54 new OpenLayers.Feature.Vector( 55 new OpenLayers.Geometry.Point(x, y), {angle: (i*36)%360-180, opacity:i/10+.1} 56 ) 57 ); 58 features.push( 59 new OpenLayers.Feature.Vector( 60 new OpenLayers.Geometry.Point(x, y), {angle: (i*36)%360, opacity:i/10+.1} 61 ) 62 ); 63 } 64 65 map.setCenter(new OpenLayers.LonLat(x-10, y), 5); 66 vectors.addFeatures(features); 67 68 var selectControl = new OpenLayers.Control.SelectFeature( 69 vectors, {hover: true}); 70 map.addControl(selectControl); 71 selectControl.activate(); 72 73 }; 74 75 </script> 76 </head> 77 <body onload="init()"> 78 <h1 id="title">Rotation Styles Example</h1> 79 <p id="shortdesc">Vector point feature symbolizers can have a <tt>rotation</tt> property. The center of the rotation is the point of the image specified by <tt>graphicXOffset</tt> and <tt>graphicYOffset</tt>.</p> 80 <div id="map"></div> 81 <div id="docs"/> 82 </body> 83 </html> -
lib/OpenLayers/Format/SLD/v1.js
old new 224 224 if(graphic.size != undefined) { 225 225 symbolizer.pointRadius = graphic.size; 226 226 } 227 if(graphic.rotation != undefined) { 228 symbolizer.rotation = graphic.rotation; 229 } 227 230 if(graphic.href != undefined) { 228 231 symbolizer.externalGraphic = graphic.href; 229 232 } -
lib/OpenLayers/Renderer/SVG.js
old new 222 222 } else { 223 223 node.setAttributeNS(null, "r", style.pointRadius); 224 224 } 225 226 if (style.rotation) { 227 var rotation = OpenLayers.String.format( 228 "rotate(${0} ${1} ${2})", [style.rotation, x, y]); 229 node.setAttributeNS(null, "transform", rotation); 230 } 225 231 } 226 232 227 233 if (options.isFilled) { -
lib/OpenLayers/Renderer/VML.js
old new 171 171 node.style.top = ((geometry.y/resolution)-(yOffset+height)).toFixed(); 172 172 node.style.width = width; 173 173 node.style.height = height; 174 node.style.flip = "y"; 174 175 175 176 // modify style/options for fill and stroke styling below 176 177 style.fillColor = "none"; … … 209 210 210 211 fill.setAttribute("src", style.externalGraphic); 211 212 fill.setAttribute("type", "frame"); 212 node.style.flip = "y";213 213 214 214 if (!(style.graphicWidth && style.graphicHeight)) { 215 215 fill.aspect = "atmost"; … … 214 214 if (!(style.graphicWidth && style.graphicHeight)) { 215 215 fill.aspect = "atmost"; 216 216 } 217 218 // additional rendering for rotated graphics 219 if (style.rotation) { 220 this.graphicRotate(node, xOffset, yOffset); 221 // make the fill fully transparent, because we now have 222 // the graphic as imagedata element. We cannot just remove 223 // the fill, because this is part of the hack described 224 // in graphicRotate 225 fill.setAttribute("opacity", 0); 226 } 217 227 } 218 228 if (fill.parentNode != node) { 219 229 node.appendChild(fill); … … 250 260 }, 251 261 252 262 /** 263 * Method: graphicRotate 264 * If a point is to be styled with externalGraphic and rotation, VML fills 265 * cannot be used to display the graphic, because rotation of graphic 266 * fills is not supported by the VML implementation of Internet Explorer. 267 * This method creates a olv:imagedata element inside the VML node, 268 * DXImageTransform.Matrix and BasicImage filters for rotation and 269 * opacity, and a 3-step hack to remove rendering artefacts from the 270 * graphic and preserve the ability of graphics to trigger events. 271 * Finally, OpenLayers methods are used to determine the correct 272 * insertion point of the rotated image, because DXImageTransform.Matrix 273 * does the rotation without the ability to specify a rotation center 274 * point. 275 * 276 * Parameters: 277 * node - {DOMElement} 278 * xOffset - {Number} rotation center relative to image, x coordinate 279 * yOffset - {Number} rotation center relative to image, y coordinate 280 */ 281 graphicRotate: function(node, xOffset, yOffset) { 282 var style = style || node._style; 283 var options = node._options; 284 285 var aspectRatio, size; 286 if (!(style.graphicWidth && style.graphicHeight)) { 287 // load the image to determine its size 288 var img = new Image(); 289 img.onreadystatechange = OpenLayers.Function.bind(function() { 290 if(img.readyState == "complete" || 291 img.readyState == "interactive") { 292 aspectRatio = img.width / img.height; 293 size = Math.max(style.pointRadius * 2, 294 style.graphicWidth || 0, 295 style.graphicHeight || 0); 296 xOffset = xOffset * aspectRatio; 297 style.graphicWidth = size * aspectRatio; 298 style.graphicHeight = size; 299 this.graphicRotate(node, xOffset, yOffset) 300 } 301 }, this); 302 img.src = style.externalGraphic; 303 304 // will be called again by the onreadystate handler 305 return; 306 } else { 307 size = Math.max(style.graphicWidth, style.graphicHeight); 308 aspectRatio = style.graphicWidth / style.graphicHeight; 309 } 310 311 var width = Math.round(style.graphicWidth || size * aspectRatio); 312 var height = Math.round(style.graphicHeight || size); 313 node.style.width = width; 314 node.style.height = height; 315 316 // Three steps are required to remove artefacts for images with 317 // transparent backgrounds (resulting from using DXImageTransform 318 // filters on svg objects), while preserving awareness for browser 319 // events on images: 320 // - Use the fill as usual (like for unrotated images) to handle 321 // events 322 // - specify an imagedata element with the same src as the fill 323 // - style the imagedata element with an AlphaImageLoader filter 324 // with empty src 325 var image = document.getElementById(node.id + "_image"); 326 if (!image) { 327 image = this.createNode("olv:imagedata", node.id + "_image"); 328 node.appendChild(image); 329 } 330 image.style.width = width; 331 image.style.height = height; 332 image.src = style.externalGraphic; 333 image.style.filter = 334 "progid:DXImageTransform.Microsoft.AlphaImageLoader(" + 335 "src='', sizingMethod='scale')"; 336 337 var rotation = style.rotation * Math.PI / 180; 338 var sintheta = Math.sin(rotation); 339 var costheta = Math.cos(rotation); 340 341 // do the rotation on the image 342 var filter = 343 "progid:DXImageTransform.Microsoft.Matrix(M11=" + costheta + 344 ",M12=" + (-sintheta) + ",M21=" + sintheta + ",M22=" + costheta + 345 ",SizingMethod='auto expand')\n" 346 347 // set the opacity (needed for the imagedata) 348 var opacity = style.graphicOpacity || style.fillOpacity; 349 if (opacity && opacity != 1) { 350 filter += 351 "progid:DXImageTransform.Microsoft.BasicImage(opacity=" + 352 opacity+")\n"; 353 } 354 node.style.filter = filter; 355 356 // do the rotation again on a box, so we know the insertion point 357 var centerPoint = new OpenLayers.Geometry.Point(-xOffset, -yOffset); 358 var imgBox = new OpenLayers.Bounds(0, 0, width, height).toGeometry(); 359 imgBox.rotate(style.rotation, centerPoint); 360 var imgBounds = imgBox.getBounds(); 361 362 node.style.left = Math.round( 363 parseInt(node.style.left) + imgBounds.left); 364 node.style.top = Math.round( 365 parseInt(node.style.top) - imgBounds.bottom); 366 }, 367 368 /** 253 369 * Method: postDraw 254 370 * Some versions of Internet Explorer seem to be unable to set fillcolor 255 371 * and strokecolor to "none" correctly before the fill node is appended to -
tests/Renderer/VML.html
old new 143 143 t.eq(node.style.width, (2 * radius) + "px", "width is correct"); 144 144 t.eq(node.style.height, (2 * radius) + "px", "height is correct"); 145 145 } 146 147 function test_VML_drawGraphic(t) { 148 if (!OpenLayers.Renderer.VML.prototype.supported()) { 149 t.plan(0); 150 return; 151 } 152 153 t.plan(6); 154 155 var r = new OpenLayers.Renderer.VML(document.body); 156 r.resolution = 1; 157 158 var node = document.createElement('div'); 159 node.id = "test" 160 node._geometryClass = "OpenLayers.Geometry.Point"; 161 162 var geometry = { 163 x: 1, 164 y: 2 165 } 166 167 var style = { 168 externalGraphic: "foo.png", 169 graphicWidth: 7, 170 graphicHeight: 10 171 } 172 173 r.drawGeometryNode(node, geometry, style); 174 175 t.eq(node.childNodes[0].id, "test_fill", "fill child node correctly created"); 176 t.eq(node.style.left, "-3px", "x of insertion point with calculated xOffset correct"); 177 t.eq(node.style.top, "-3px", "y of insertion point with calculated yOffset correct"); 178 179 style.rotation = 90; 180 181 r.drawGeometryNode(node, geometry, style); 182 183 t.eq(node.childNodes[1].id, "test_image", "image child node correctly created"); 184 t.eq(node.style.left, "-4px", "x of insertion point of rotated image correct"); 185 t.eq(node.style.top, "-4px", "y of insertion point of rotated image correct"); 186 } 146 187 147 188 function test_VML_drawlinestring(t) { 148 189 if (!OpenLayers.Renderer.VML.prototype.supported()) {
