博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenLayers源码学习笔记--- OpenLayers中样式相关
阅读量:6228 次
发布时间:2019-06-21

本文共 8199 字,大约阅读时间需要 27 分钟。

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

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

转载于:https://www.cnblogs.com/xignzou/archive/2012/07/26/2609894.html

你可能感兴趣的文章
VS2010 调试C++项目 fatal error LNK1123 错误解决办法
查看>>
调整linux的时钟
查看>>
ObjectOutputStream和ObjectInputStream
查看>>
static作用
查看>>
IT架构之IT架构标准——思维导图
查看>>
ZOJ3827 ACM-ICPC 2014 亚洲区域赛的比赛现场牡丹江I称号 Information Entropy 水的问题...
查看>>
List、Map和Set实现类
查看>>
Android Fragment 真正彻底的解决(下一个)
查看>>
zoj 3659 并检查集合
查看>>
VS2010如何调试IIS上的网站
查看>>
iPhone 6/plus iOS Safari fieldset border 边框消失
查看>>
Xms Xmx PermSize MaxPermSize 区别
查看>>
【转】预装(push)lib64中so文件查找错误
查看>>
《Python简明教程》总结
查看>>
构造 - HDU 5402 Travelling Salesman Problem
查看>>
[转]图解分布式一致性协议Paxos
查看>>
【SSH2(实用文章)】--Struts2文件上传和下载的例子
查看>>
Rust初步(七):格式化
查看>>
微服务架构的设计模式
查看>>
【C++】继承时构造函数和析构函数
查看>>