zoukankan      html  css  js  c++  java
  • OpenLayers源码学习笔记 OpenLayers中样式相关

              Style样式这块其实在整个Openlayers中不算什么特别大重点,但是作为显示的一个元素,这里相关的内容特比多,经常看到有同事因为用错这块导致的各种问题。所以也就整理了下...

    一、相关模块功能类比较多,这里先介绍下各个关键类在这个样式渲染环节中的作用和功能:

          Symbolizer  样式,记录样式信息的Object。特点:样式只针对具体的点、线、面等对象(点对象所需的样式和面对像所需的样式可能不同,查看其API,集合用户对象可以知道需要设置怎样的样式属性来控制对象显示)。一般不需要用户构建,而是由Style创建出来,内部在使用的时候通过css或者canvas的画笔控制来显示不同效果。

          Style   样式类,定义某种状态的完全样式,点线面等全部包括在内。内含defaultStyle属性记录所设置的样式(属性-值)集合对象Object。提供了createSymbolizer方法来为具体的点、线等对象提供Symbolizer样式。

          关于 style中对rule属性的使用控制…产看下面的设计代码分析内容

           StyleMap: 图层样式,定义多种状态下的图层样式,其属性styles中存储由key(‘state’), value(‘Style’) 组成的状态-样式键值对构成。  StyleMap信息被赋予到使用样式显示的Vector图层,默认支持四种样式,下面是OP中StyleMap样式的初始状态

    Stylemap.styles = {
     
                "default": new OpenLayers.Style(
     
                    OpenLayers.Feature.Vector.style["default"]),
     
                "select": new OpenLayers.Style(
     
                    OpenLayers.Feature.Vector.style["select"]),
     
                "temporary": new OpenLayers.Style(
     
                    OpenLayers.Feature.Vector.style["temporary"]),
     
                "delete": new OpenLayers.Style(
     
                    OpenLayers.Feature.Vector.style["delete"])
     
    }

             使用的过程中,vector根据不同状态获取不同样式,然后将使用对应的样式显示feature对象。

            OpenLayer.Layer.Vector  矢量图层,是最终的显示承载对象,根据和map,控件的交互,可以获取,设置当前feature的状态,然后从stylemap中读取样式,应用到具体的feature显示上。

           OpenLayer.Feature.Vector  矢量对象,要显示的基本对象,记录几何信息geometry等,默认使用的时候会应用图层样式,如果对feature单独设置样式,则不管什么都以设置的样式作为显示依据,而不去管图层样式怎么设置

           Renderer  使用样式和几何对象属性等来展示Feature要素的最终工具,根据不同浏览器和支持情况选用不同的渲染工具,支持的VML,SVG,Canvas。

           Rule规则定义,通过定义规则来指定不同情况下的样式属性值,来决定最终样式采用的显示属性(定义规则..)

           Filter: Rule规则定义的具体规则都是由Filter来实现和完成的的,规则的具体定义和执行者……

           Context:我们知道Style上的${XXX}取值方法,通过XXX命名的属性可以动态设置属性的值作为样式的备选值(参加下面的示例1)

           Context提供了另外一种更为直接的方法,XXX不指定属性名,而直接指定对应的方法,在方法内部完成由属性值–>样式属性的转换。使用方式类似,相比之下Context更为直接,直接使用方法,接受feature作为参数,内部通过复杂的逻辑处理来获取最终结果,因此提供了更为灵活和多边的样式设置方式。Context可以提供比直接取值更大的操作变化。下面给出两个示例(都是从OpenLayers的examples中直接借过来的说..完成示例可以查看OpenLayers/examples/styles_context.html     OpenLayers/examples/styles_map.html)

         示例一:使用${XXX},xxx代表属性名

    //feature添加type属性
                 var features = new Array(50);
                 for (var i=0; i<features.length; i++) {
                    features[i] = new OpenLayers.Feature.Vector(
                        new OpenLayers.Geometry.Point(
                            (360 * Math.random()) - 180, (180 * Math.random()) - 90
                        ), {
                            type: 5 + parseInt(5 * Math.random())
                        }
                    );
                }
               //设置${}取值,使用type的值来设置点对象半径
     
              var myStyles = new OpenLayers.StyleMap({
                    "default": new OpenLayers.Style({
                        pointRadius: "${type}", // 通过属性名取值,作为样式的值
                        fillColor: "#ffcc66",
                        strokeColor: "#ff9933",
                        strokeWidth: 2,
                        graphicZIndex: 1
                    }),
                    "select": new OpenLayers.Style({
                        fillColor: "#66ccff",
                        strokeColor: "#3399ff",
                        graphicZIndex: 2
                    })
                });

    示例二:使用${XXX},XXX代表调用方法

    var features = new Array(50);
                for (var i=0; i<features.length; i++) {
                    features[i] = new OpenLayers.Feature.Vector(
                        new OpenLayers.Geometry.Point(
                            (360 * Math.random()) - 180, -90 * Math.random()
                        ), {
                            type: 5 + parseInt(5 * Math.random())
                        }
                    );
                }
                // 定义context,主要是定义根据属性获取样式值的方法create the layer styleMap by giving the default style a context
                var colors = ["red", "green", "blue"];
                var context = {
                    getColor: function(feature) {
                        var region = parseInt((feature.geometry.x + 180) / 120);
                        return colors[region];
                    },
                    getSize: function(feature) {
                        return feature.attributes["type"] / map.getResolution() * .703125;
                    }
                };
               //使用方法,设置样式..
               var template = {
                    pointRadius: "${getSize}", // using context.getSize(feature)
                    fillColor: "${getColor}" // using context.getColor(feature)
                };
                //生成样式并最终使用样式
                var style = new OpenLayers.Style(template, {context: context});
                var layer2 = new OpenLayers.Layer.Vector('Points', {
                    styleMap: new OpenLayers.StyleMap(style),
                    renderers: renderer
                });

    二、样式的使用。我们所使用的样式中一般有两个样式的最终源头(即用户可以设置修改样式的方法)

             1、  设置layer.vector的style(Object对象)或者styleMap(key: Style对象)样式。style直接使用,styleMap用来根据featur的几何对象和状态来设置对应的样式,这个环节中使用了对规则rule和context的相关使用,后面专门介绍。

             2、  直接设置feature的样式Style。Object类型

            使用优先级比较  feature.style  >  layer.style   > layer.StyleMap

            前两个都是简单的Object对象,意味着用户知道具体的feature类型是点还是线面,知道需要设置哪些样式才有效,然后设置固定样式,所以针对性好,但是不具备状态属性和,也不存在对rule和context使用时候的灵活性。。。。关于这块的区别在下面的分析中会看的更清楚些

    三、最后来说明下最标准完备的StyleMap,Style,Rule,Context,Symbolizer,Vector,Renderer的关系。。(相互之间调用和生成的顺序关系),我们假设设置StyleMap:

      1. 关于StyleMap的初始化,这里贴出StyleMap的构造函数源码说明:

        initialize: function (style, options) {
                this.styles = {
                    "default": new OpenLayers.Style(
                        OpenLayers.Feature.Vector.style["default"]),
                    "select": new OpenLayers.Style(
                        OpenLayers.Feature.Vector.style["select"]),
                    "temporary": new OpenLayers.Style(
                        OpenLayers.Feature.Vector.style["temporary"]),
                    "delete": new OpenLayers.Style(
                        OpenLayers.Feature.Vector.style["delete"])
                };
                 
                // take whatever the user passed as style parameter and convert it
                // into parts of stylemap.
                if(style instanceof OpenLayers.Style) {
                    // user passed a style object
                    this.styles["default"] = style;
                    this.styles["select"] = style;
                    this.styles["temporary"] = style;
                    this.styles["delete"] = style;
                } else if(typeof style == "object") {
                    for(var key in style) {
                        if(style[key] instanceof OpenLayers.Style) {
                            // user passed a hash of style objects
                            this.styles[key] = style[key];
                        } else if(typeof style[key] == "object") {
                            // user passsed a hash of style hashes
                            this.styles[key] = new OpenLayers.Style(style[key]);
                        } else {
                            // user passed a style hash (i.e. symbolizer)
                            this.styles["default"] = new OpenLayers.Style(style);
                            this.styles["select"] = new OpenLayers.Style(style);
                            this.styles["temporary"] = new OpenLayers.Style(style);
                            this.styles["delete"] = new OpenLayers.Style(style);
                            break;
                        }
                    }
                }
                OpenLayers.Util.extend(this, options);
            },

        代码分析,其设计基本如下:第一步默认读取vector中定义的样式来完成初始化。。第二步通过样式参数来设置具体的用户样式,

        分多种情况对象:

        1)         独立的样式对象Style,将四种状态样式都设置为此,即相当于没有状态区别

        2)         样式组成的键值对key:Style(或者Object),读取提供的样式,覆盖默认值,如果后面的值不是Style对象,内部做封装后设置

        3)         只是一个Object对象,直接封装成Style样式,然后同1)

      2. 关于StyleMap—>style—>Symbolizer的转换过程,中间使用到的Rule,filter,context,等:

        1)       矢量图层使用StyleMap的createSymbolizer: function(feature, intent)方法来获取一个Symbolizer对象。

                  参数: feature  具体的矢量元素,包含几何信息,attribute等

                  Intent: 记录feature的当前状态,”default”或者”select”….

        2)       查看StyleMap的源码会发现在其CreateSymbolizer中最终是通过调用Style的CreateSymbolizer方法来获取的样式结果的。源码如下:

                  this.styles[intent].createSymbolizer(feature)

        3)       Style的CreateSymbolizer方法分解:

                 A、关于context的使用:

                   通过方法调用createLiterals ---> createLiteral,最终由OpenLayers.String.format 来完成对属性值标记${property} 到样式值的转换

        OpenLayers.Style.createLiteral = function(value, context, feature, property) {
            if (typeof value == "string" && value.indexOf("${") != -1) {
                value = OpenLayers.String.format(value, context, [feature, property]);
                value = (isNaN(value) || !value) ? value : parseFloat(value);
            }
            return value;
        };
            return value;
        } ;

            B、关于Rule的使用

                      同样在createSymbolizer方法中

                      a)         通过调用rule的evaluate方法来判断是否对当前Feature应用规则,其中rule的evaluate方法调用的是具体Filter中的同名方法实现

                      b)         如果使用规则,则调用applySymbolizer(rule, style, feature)来实现对规则中定义的样式添加到返回样式结果中。

                      c)         多个规则多次应用。

        举例说明:如果针对feature的属性foo来设置,当foo的值小于25的时候我们使用蓝色图片,但其位于25和50之间,使用绿色图片,位于50和75之间使用使用金色图片,其他else的情况下使用默认图片。那么我们则需要根据不同条件定义不同的规则,需要4个rule对象,rules数组的定义如下:(代码来自OpenLayers/examples/style_rule.js),可运行对应的案例查看结果(完成示例参考OpenLayers/examples/style-rules.html)

        rules: [
                        new OpenLayers.Rule({
                            // a rule contains an optional filter
                            filter: new OpenLayers.Filter.Comparison({
                                type: OpenLayers.Filter.Comparison.LESS_THAN,
                                property: "foo", // the "foo" feature attribute
                                value: 25
                            }),
                            // if a feature matches the above filter, use this symbolizer
                            symbolizer: {
                                externalGraphic: "../img/marker-blue.png"
                            }
                        }),
                        new OpenLayers.Rule({
                            filter: new OpenLayers.Filter.Comparison({
                                type: OpenLayers.Filter.Comparison.BETWEEN,
                                property: "foo",
                                lowerBoundary: 25,
                                upperBoundary: 50
                            }),
                            symbolizer: {
                                externalGraphic: "../img/marker-green.png"
                            }
                        }),
                        new OpenLayers.Rule({
                            filter: new OpenLayers.Filter.Comparison({
                                type: OpenLayers.Filter.Comparison.BETWEEN,
                                property: "foo",
                                lowerBoundary: 50,
                                upperBoundary: 75
                            }),
                            symbolizer: {
                                externalGraphic: "../img/marker-gold.png"
                            }
                        }),
                        new OpenLayers.Rule({
                            // apply this rule if no others apply
                            elseFilter: true,
                            symbolizer: {
                                externalGraphic: "../img/marker.png"
                            }
                        })
                    ]
      3.    关于addUniqueValueRules方法,该方法可以视为是通过Rule和Context的特殊情况,等值判断Filter来实现的一个特例.(其内部具体实现过程和使用方式有所不同,参考openlayers/examples/styles-unique.html示例。,但是总觉没那么多必要专门弄个这么接口,想了解的话可以查看Openlayer/examples/styles-unique.html)

        总结: Style提供了方便灵活地使用方式,但是也给用户当使用带来了一定的不便,初学者会被这些复杂的使用结构搞混,以至于不知道如何具体使用。感觉这块提供的方式过于灵活了,不如限制严格的规范。上面只是简单的分析了其中的调用原理,对于相对内部结构有所了解的朋友但愿能起到一定的作用。

        如果你想了解如何使用,个人感觉最好的熟悉方法还是查看案例,然后按照最标准的使用方法来,上面的内容就当帮助你理解使用规范以防止出错….

  • 相关阅读:
    抽象类和接口
    【转载】Java 透析C/S和B/S结构
    java中的基本数据类型
    java之IO流详解(一)
    Yearning和inception搭建MySQL审核平台
    一个适合变化的产品部署集成包(nginx+jdk+tomcat+nodejs+mysql+redis+mongo+MYSQL主主(读写分离)集群建立+代码包+持续上线+备份)
    CPU计算密集型和IO密集型
    ansible结合SHELL搭建自己的CD持续交付系统
    JENKINS系统的安装部署
    DATAGUARD实施文档
  • 原文地址:https://www.cnblogs.com/xignzou/p/2609894.html
Copyright © 2011-2022 走看看