Ticket #1433: 1433-r6522-A1.patch
| File 1433-r6522-A1.patch, 11.5 kB (added by ahocevar, 5 months ago) |
|---|
-
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/Renderer/SVG.js
old new 221 221 } else { 222 222 node.setAttributeNS(null, "r", style.pointRadius); 223 223 } 224 225 if (style.rotation) { 226 var rotation = OpenLayers.String.format( 227 "rotate(${0} ${1} ${2})", [style.rotation, x, y]); 228 node.setAttributeNS(null, "transform", rotation); 229 } 224 230 } 225 231 226 232 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 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 = 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.src = style.externalGraphic; 290 aspectRatio = img.width / img.height; 291 size = Math.max(style.pointRadius * 2, style.graphicWidth || 0, 292 style.graphicHeight || 0); 293 xOffset = xOffset * aspectRatio; 294 } else { 295 size = Math.max(style.graphicWidth, style.graphicHeight); 296 aspectRatio = style.graphicWidth / style.graphicHeight; 297 } 298 299 width = Math.round(style.graphicWidth || size * aspectRatio); 300 height = Math.round(style.graphicHeight || size); 301 node.style.width = width; 302 node.style.height = height; 303 304 // Three steps are required to remove artefacts for images with 305 // transparent backgrounds (resulting from using DXImageTransform 306 // filters on svg objects), while preserving awareness for browser 307 // events on images: 308 // - Use the fill as usual (like for unrotated images) to handle 309 // events 310 // - specify an imagedata element with the same src as the fill 311 // - style the imagedata element with an AlphaImageLoader filter 312 // with empty src 313 var image = document.getElementById(node.id + "_image"); 314 if (!image) { 315 image = this.createNode("v:imagedata", node.id + "_image"); 316 node.appendChild(image); 317 } 318 image.style.width = width; 319 image.style.height = height; 320 image.src = style.externalGraphic; 321 image.style.filter = 322 "progid:DXImageTransform.Microsoft.AlphaImageLoader(" + 323 "src='', sizingMethod='scale')"; 324 325 var rotation = style.rotation * Math.PI / 180; 326 var sintheta = Math.sin(rotation); 327 var costheta = Math.cos(rotation); 328 329 // do the rotation on the image 330 var filter = 331 "progid:DXImageTransform.Microsoft.Matrix(M11=" + costheta + 332 ",M12=" + (-sintheta) + ",M21=" + sintheta + ",M22=" + costheta + 333 ",SizingMethod='auto expand')\n" 334 335 // set the opacity (needed for the imagedata) 336 var opacity = style.graphicOpacity || style.fillOpacity; 337 if (opacity && opacity != 1) { 338 filter += 339 "progid:DXImageTransform.Microsoft.BasicImage(opacity=" + 340 opacity+")\n"; 341 } 342 node.style.filter = filter; 343 344 // do the rotation again on a box, so we know the insertion point 345 var centerPoint = new OpenLayers.Geometry.Point(-xOffset, -yOffset); 346 var imgBox = new OpenLayers.Bounds(0, 0, width, height).toGeometry(); 347 imgBox.rotate(style.rotation, centerPoint); 348 var imgBounds = imgBox.getBounds(); 349 350 node.style.left = Math.round( 351 parseInt(node.style.left) + imgBounds.left); 352 node.style.top = Math.round( 353 parseInt(node.style.top) - imgBounds.bottom); 354 }, 355 356 /** 253 357 * Method: postDraw 254 358 * Some versions of Internet Explorer seem to be unable to set fillcolor 255 359 * and strokecolor to "none" correctly before the fill node is appended to -
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); 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()) {
