OpenLayers OpenLayers

Ticket #1433: 1433-r6749-A2.patch

File 1433-r6749-A2.patch, 13.0 kB (added by ahocevar, 5 months ago)

Updated patch; example is now formatted properly

  • 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  
    235235                if(graphic.size != undefined) { 
    236236                    symbolizer.pointRadius = graphic.size; 
    237237                } 
     238                if(graphic.rotation != undefined) { 
     239                    symbolizer.rotation = graphic.rotation; 
     240                } 
    238241                if(graphic.href != undefined) { 
    239242                    symbolizer.externalGraphic = graphic.href; 
    240243                } 
  • lib/OpenLayers/Renderer/SVG.js

    old new  
    222222            } else { 
    223223                node.setAttributeNS(null, "r", style.pointRadius); 
    224224            } 
     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            } 
    225231        } 
    226232         
    227233        if (options.isFilled) { 
  • lib/OpenLayers/Renderer/VML.js

    old new  
    171171                node.style.top = ((geometry.y/resolution)-(yOffset+height)).toFixed(); 
    172172                node.style.width = width; 
    173173                node.style.height = height;     
     174                node.style.flip = "y"; 
    174175                 
    175176                // modify style/options for fill and stroke styling below 
    176177                style.fillColor = "none"; 
     
    209210                 
    210211                fill.setAttribute("src", style.externalGraphic); 
    211212                fill.setAttribute("type", "frame"); 
    212                 node.style.flip = "y"; 
    213213                 
    214214                if (!(style.graphicWidth && style.graphicHeight)) { 
    215215                  fill.aspect = "atmost"; 
     
    214214                if (!(style.graphicWidth && style.graphicHeight)) { 
    215215                  fill.aspect = "atmost"; 
    216216                }                 
     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                } 
    217227            } 
    218228            if (fill.parentNode != node) { 
    219229                node.appendChild(fill); 
     
    250260    }, 
    251261 
    252262    /** 
     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    /** 
    253369     * Method: postDraw 
    254370     * Some versions of Internet Explorer seem to be unable to set fillcolor 
    255371     * and strokecolor to "none" correctly before the fill node is appended to 
  • tests/Renderer/VML.html

    old new  
    143143        t.eq(node.style.width, (2 * radius) + "px", "width is correct"); 
    144144        t.eq(node.style.height, (2 * radius) + "px", "height is correct"); 
    145145    } 
     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    } 
    146187 
    147188    function test_VML_drawlinestring(t) { 
    148189        if (!OpenLayers.Renderer.VML.prototype.supported()) {