Ticket #1433: 1433-r6645-A2.patch
| File 1433-r6645-A2.patch, 12.9 kB (added by ahocevar, 5 months ago) |
|---|
-
tests/Renderer/test_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); 146 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 } 187 147 188 function test_VML_drawlinestring(t) { 148 189 if (!OpenLayers.Renderer.VML.prototype.supported()) { 149 190 t.plan(0); -
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"; 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 v: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("v: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 -
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) { -
examples/styles-rotation.html
old new 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <style type="text/css"> 4 #map { 5 width: 800px; 6 height: 475px; 7 border: 1px solid black; 8 } 9 </style> 10 <script src="../lib/OpenLayers.js" type="text/javascript"></script> 11 <script type="text/javascript"> 12 13 var map; 14 var vectors; 15 16 function init(){ 17 map = new OpenLayers.Map('map'); 18 var wms = new OpenLayers.Layer.WMS( 19 "OpenLayers WMS", 20 "http://labs.metacarta.com/wms/vmap0", 21 {layers: 'basic'} 22 ); 23 24 vectors = new OpenLayers.Layer.Vector( 25 "Simple Geometry", 26 { 27 styleMap: new OpenLayers.StyleMap({ 28 "default": { 29 externalGraphic: "../img/marker-gold.png", 30 //graphicWidth: 17, 31 graphicHeight: 20, 32 graphicYOffset: -19, 33 rotation: "${angle}", 34 fillOpacity: "${opacity}" 35 }, 36 "select": { 37 cursor: "crosshair", 38 externalGraphic: "../img/marker.png" 39 } 40 }) 41 } 42 ); 43 44 map.addLayers([wms, vectors]); 45 46 var features = []; 47 var x = -111.04; 48 var y = 45.68; 49 for(var i = 0; i < 10; i++){ 50 x += i * .5; 51 y += i * .1; 52 features.push( 53 new OpenLayers.Feature.Vector( 54 new OpenLayers.Geometry.Point(x, y), {angle: (i*36)%360-180, opacity:i/10+.1} 55 ) 56 ); 57 features.push( 58 new OpenLayers.Feature.Vector( 59 new OpenLayers.Geometry.Point(x, y), {angle: (i*36)%360, opacity:i/10+.1} 60 ) 61 ); 62 } 63 64 map.setCenter(new OpenLayers.LonLat(x-10, y), 5); 65 vectors.addFeatures(features); 66 67 var selectControl = new OpenLayers.Control.SelectFeature( 68 vectors, {hover: true}); 69 map.addControl(selectControl); 70 selectControl.activate(); 71 72 }; 73 74 </script> 75 </head> 76 <body onload="init()"> 77 <div id="map"></div> 78 <p>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> 79 </body> 80 </html> -
lib/OpenLayers/Format/SLD/v1.js
old new 235 235 if(graphic.size != undefined) { 236 236 symbolizer.pointRadius = graphic.size; 237 237 } 238 if(graphic.rotation != undefined) { 239 symbolizer.rotation = graphic.rotation; 240 } 238 241 if(graphic.href != undefined) { 239 242 symbolizer.externalGraphic = graphic.href; 240 243 }
