GeoServer能够提供WMS服务,采用SLD来渲染地图样式。如何动态地改变地图的样式,来完成一些特殊的功能呢?可以参照demo中的wms-sld_body示例,做法如下:(下列代码是在OpenLayers中的js代码)
var sld = "<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/sld [url]http://schemas.opengeospatial.net/sld/1.0.0/StyledLayerDescriptor.xsd[/url]"><NamedLayer><Name>AAA207</Name><UserStyle><FeatureTypeStyle><Rule><Filter><PropertyIsEqualTo><PropertyName>DIENSTNAAM</PropertyName><Literal>%literal%</Literal></PropertyIsEqualTo></Filter><PolygonSymbolizer><Fill><CssParameter name="fill">#000099</CssParameter></Fill></PolygonSymbolizer></Rule><Rule><ElseFilter/><PolygonSymbolizer><Fill><CssParameter name="fill">#bfcaea</CssParameter></Fill><Stroke><CssParameter name="stroke">#a6c6ff</CssParameter><CssParameter name="stroke-width">1.0</CssParameter></Stroke></PolygonSymbolizer></Rule></FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>";
layer = new OpenLayers.Layer.WMS.Untiled( "Beheersgebieden", "http://www.rijkswaterstaat.nl/services/geoservices/basispakket/grenzen?", {layers: "AAA207", "format":"image/gif", "transparent":"true"}, {"numZoomLevels": 1, "ratio":1, isBaseLayer: true} );
newsld = sld.replace("%literal%", 【某个属性值】);
layer.mergeNewParams({"sld_body":newsld });
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 version=“1.0.0”><UserLayer><Name>topp:faro</Name><UserStyle><Name>UserSelection</Name><FeatureTypeStyle><Rule><Filter xmlns:gml=“http://www.opengis.net/gml”><PropertyIsEqualTo><PropertyName>STATE_NAME</PropertyName><Literal>Illinois</Literal></PropertyIsEqualTo></Filter><PolygonSymbolizer><Fill><CssParameter name=“fill”>#FF0000</CssParameter></Fill></PolygonSymbolizer></Rule><Rule><LineSymbolizer><Stroke/></LineSymbolizer></Rule></FeatureTypeStyle></UserStyle></UserLayer></StyledLayerDescriptor>', //这里的SLD_BODY为XML里的原格式,不能变
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这个参数就行了。