众所周知,GeoServer能够提供WMS服务,采用SLD来渲染地图样式。如何动态地改变地图的样式,来完成一些特殊的功能呢?可以参照demo中的wms-sld_body示例,做法如下:(下列代码是在OpenLayers中的js代码)
复制代码
好象在sld 前面要加入 layer.mergeNewParams({"sld_body":newsld }); 这里有一个致命的缺陷就是SLD作为URL参数传递到服务器,很容易超过URL长度限制。 |
在geoserver中动态改变SLD的过程:
1.获得原始的SLD文件,这个SLD文件可以是geoserver里的demo,也可以使自己构造的,只要符合ogc规范可以在geoserver里应用到layer上,openlayers有OpenLayers.loadURL这个函数可以用,java里面可以使用filereader读取文件;
2.根据自己的需要修改SLD文件里的参数,这个可以在js或JAVA里进行,就是将文件内容读取为字符串,对字符串进行操作;
3.将修改好的SLD文件(后缀可以是sld或xml,geoserver都可以加载的)加载到相关的layer上,openlayers里可以使用OpenLayers.Layer.WMS这个函数(也可以使用layer.mergeNewParams这个函数,不过sld的长度会受到限制)。
在使用OpenLayers.Layer.WMS这个函数时,其参数的设置很重要,我设置了很久都没有成功,最后在师兄的帮助下才配置好,而且我们还查询了很多英文的相关论坛。以下的一个例子可以说明设置参数的一些规则:
mapa = new OpenLayers.Map('map', options);
// setup tiled layer SLD: "http://deltha:8080/SLD/mapa.sld",
faro= new OpenLayers.Layer.WMS(
"topp:mapacuba - Tiled", "http://deltha:8080/geoserver/wms",
{
layers: 'topp:faro‘,
styles: '',
height: '300',
width: '800',
srs: 'EPSG:4267',
format: 'image/png',
tiled: 'true',
tilesOrigin : "-85.49711392680179,19.65266328193469"
},
{buffer: 0}
);
map.addLayers([faro]);
mapa.mergeNewParams({sld:'http://localhost:8080/SLD/faros.sld'});
mapa.redraw();
这样设置是不会成功的,地图可以显示,但是通过mapa.mergeNewParams({sld:'http://localhost:8080/SLD/faros.sld'})和mapa.redraw()却无法更改地图的sld。
因为wms请求要么就需要layers和styles两个参数,要么就只需要sld或sld_body中的一个参数。
上面的例子可以这样设置:
faro= new OpenLayers.Layer.WMS(
"topp:mapacuba - Tiled", "http://deltha:8080/geoserver/wms",
{
//layers: 'topp:faro,
//styles: '',
sld_body:
'<StyledLayerDescriptor%20version%3D%221.0.0%22><UserLayer><Name>topp:faro</Name><UserStyle><Name>UserSelection</Name><FeatureTypeStyle><Rule><Filter%20xmlns:gml%3D%22http://www.opengis.net/gml%22><PropertyIsEqualTo><PropertyName>STATE_NAME</PropertyName><Literal>Illinois</Literal></PropertyIsEqualTo></Filter><PolygonSymbolizer><Fill><CssParameter%20name%3D%22fill%22>%23FF0000</CssParameter></Fill></PolygonSymbolizer></Rule><Rule><LineSymbolizer><Stroke/></LineSymbolizer></Rule></FeatureTypeStyle></UserStyle></UserLayer></StyledLayerDescriptor>',
height: '300',
width: '800',
srs: 'EPSG:4267',
format: 'image/png',
tiled: 'true',
tilesOrigin : "-85.49711392680179,19.65266328193469"
},
{buffer: 0}
);
map.addLayers([faro]);
这样只需要提前修改sld_body中的内容就可以修改地图的sld。如果有一个sld文件,可以用sld:'http://localhost:8080/SLD/faros.sld'替换sld_body这个参数就行了。
以下是我转的一些英文论坛里牛人的意见(我就不翻译了^_^):
To make the HTTP-GET methods more practical for use, the SLD can also be
used in
one of two different modes depending on whether the LAYERS parameter is
present in
the request. If it is not present, then all layers identified in the SLD
document are
rendered with all defined styles, which is equivalent to the XML-POST method
of usage.
If the LAYERS parameter is present, then only the layers identified by that
parameter are
rendered and the SLD is used as a “style library”.
When an SLD is used as a style library, the STYLES CGI parameter is
interpreted in the
usual way in the GetMap request, except that the handling of the style names
is
organized so that the styles defined in the SLD take precedence over the
named styles
stored within the map server.