前回の投稿では、SLDReaderを利用して、SLD形式で定義されたスタイル情報を読み取り、OpenLayersで使用できるスタイルに変換し利用しました。今回は、その続きで、SLDReaderを利用して、地図の解像度によって、アイコンのサイズを変更できるかを試してました。
まず最初に、SLDのUOM(Unit of Measure)属性が設定できないか調べました。SLDには、UOMという属性が設定でき、UOMを設定することで、スタイルのサイズを地図の単位(例えばメートル)で指定することが可能になります。
UOMの概要
- UOMは、スタイルのプロパティに単位を指定する属性です。
- 主に、PointSymbolizerやLineSymbolizer、PolygonSymbolizerなどのサイズや幅を設定する際に使用されます。
- 例えば、uom=”http://www.opengis.net/ogc/metre”を指定すると、サイズが地図上のメートル単位で解釈されます。
UOMを含むSLDを、SLDReaderで利用しようと考えましたが、公式サイトによると、SLDReaderは現時点でUOMに対応していないとのことです。UOMを必要とする場合は、SLDReaderで生成したスタイルをカスタマイズする必要があるとのことです。
UOM使用例
だめもとで、UOMを設定したSLDを読み込ませてみました。
s_aed_uom.txt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-16" standalone="no"?> <StyledLayerDescriptor version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <NamedLayer> <Name>AED設置施設</Name> <UserStyle> <Title>AED設置施設</Title> <Abstract>AED設置施設</Abstract> <FeatureTypeStyle> <Rule> <Name>0</Name> <Title>AED設置施設</Title> <PointSymbolizer> <Graphic> <ExternalGraphic> <OnlineResource xlink:type="simple" xlink:href="/OpenLayersSample/SLDReader/images/s_aed.svg" /> <Format>image/svg+xml</Format> </ExternalGraphic> <Size uom="http://www.opengis.net/ogc/metre">30</Size> </Graphic> </PointSymbolizer> </Rule> </FeatureTypeStyle> </UserStyle> </NamedLayer> </StyledLayerDescriptor> |
UOM設定後の地図
仕様通りですが、アイコンのサイズが変化しません。

jsコード
仕方ないので、SLDReaderで生成されたスタイルをカスタマイズし、地図の解像度に基づいてサイズを調整することで、再現しました。
※SLDReaderで生成されたスタイルでは、SLDのサイズが格納されていないので、SLDReader本体ででsldSizeを設定しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function createDynamicStyleFunction(sldUrl) { const sldText = getText(sldUrl); const sldObject = SLDReader.Reader(sldText); const sldLayer = SLDReader.getLayer(sldObject); const sldStyle = SLDReader.getStyle(sldLayer); const featureTypeStyle = sldStyle.featuretypestyles[0]; const olStyleFunction = SLDReader.createOlStyleFunction(featureTypeStyle); const dynamicStyleFunction = (feature, resolution) => { // SLDスタイルを取得 const styles = olStyleFunction(feature, resolution); // スタイルを更新(アイコンサイズを変更) styles.forEach((style) => { const image = style.getImage(); if (image && image instanceof ol.style.Icon) { const newScale = image.sldSize / resolution; image.setScale(newScale); // サイズをスケールで調整 } }); return styles; }; return dynamicStyleFunction; } const dynamicStyleFunction = createDynamicStyleFunction( '/OpenLayersSample/SLDReader/styles/s_aed.txt'); const layer2 = new ol.layer.Vector({ source: new ol.source.Vector({ url: '/OpenLayersSample/SLDReader/data/aed.geojson', format: new ol.format.GeoJSON(), }), style: dynamicStyleFunction, }); |
カスタマイズ後の地図
地図の解像度によって、アイコンのサイズが変化しています。

まとめ
UOMが対応していれば完璧だったのですが、しょうがないですね。今後も引き続きテキストやラインも試してみようと思います。