在GeoServer中发布样式用到SLD,需要在业务中进行SLD的生成。
SLD本身是特定的XML。
JavaScript处理JSON数据比较灵活,但是对于XML处理相对复杂一点。
因此将SLD转换为JSON进行处理。
由于SLD涉及到的标签非常多,规则比较灵活,目前只支持单一符号、分类符号和等级符号的SLD以及文本标注的SLD。
目前支持创建的类型包括:
PointSymbolizer
、LineSymbolizer
、PolygonSymbolizer
以及TextSymbolizer
.
其中PointSymbolizer
支持创建简单点符号和图标类XML格式的字符串;
关键代码:
/**
* 符号创建工厂类
*/
const SymbolFactory = {
createPointSymbol: (options) => {
if (options.wellKnownName) return SymbolFactory.createPointSimpleSymbol(options);
return SymbolFactory.createPointExternalSymbol(options);
},
/**
* 创建简单点符号的XML格式的字符串
* @param {Object} options 配置参数
* @example options = {
* WellKnownName:"square",// 也可以是 "circle" "triangle" "star" "cross" "x" "square"
* fill:"#FF0000",
* fillOpacity: 0.5,
* stroke:"#FF0000",
* strokeWidth: 1.0,
* strokeOpacity: 1.0,
* opacity: 1.0,
* size: 8.0,
* rotation: 0.0
* }
*/
createPointSimpleSymbol: (options) => {
return `<PointSymbolizer>
<Graphic>
<Mark>
<WellKnownName>${options.wellKnownName || "square"}</WellKnownName>
<Fill>
<CssParameter name="fill">${options.fill || "#333333"}</CssParameter>
<CssParameter name="fill-opacity">${options.fillOpacity || 1.0}</CssParameter>
</Fill>
<Stroke>
<CssParameter name="stroke">${options.stroke || "#333333"}</CssParameter>
<CssParameter name="stroke-width">${options.strokeWidth || 1.0}</CssParameter>
<CssParameter name="stroke-opacity">${options.strokeOpacity || 1.0}</CssParameter>
</Stroke>
</Mark>
<Opacity>${options.opacity || 1.0}</Opacity>
<Size>${options.size || 8.0}</Size>
<Rotation>${options.rotation || 0.0}</Rotation>
</Graphic>
</PointSymbolizer>`;
},
/**
* 创建图标类点符号的XML格式的字符串;
* 暂只支持base64图片格式,进一步扩展参考:https://dev.luciad.com/portal/productDocumentation/LuciadFusion/docs/articles/faq/ogc/external_graphic_icon.html?subcategory=ogc_sld
* @param {Object} options 配置参数
* @example options = {
* base64Content:"base64格式的图片",
* anchorPointX: 0.5,
* anchorPointY: 0.5,
* opacity: 1.0,
* size: 8.0,
* rotation: 0.0
* }
*/
createPointExternalSymbol: (options) => {
return `<PointSymbolizer uom="http://www.opengeospatial.org/se/units/pixel">
<Graphic>
<ExternalGraphic>
<InlineContent encoding="base64">
${options.base64Content}
</InlineContent>
<Format>image/png</Format>
</ExternalGraphic>
<Size>${options.size || 8.0}</Size>
<Opacity>${options.opacity || 1.0}</Opacity>
<AnchorPoint>
<AnchorPointX>${options.anchorPointX || 0.0}</AnchorPointX>
<AnchorPointY>${options.anchorPointY || 0.0}</AnchorPointY>
</AnchorPoint>
<Rotation>${options.rotation || 0.0}</Rotation>
</Graphic>
</PointSymbolizer>`;
},
/**
* 创建线符号的XML格式的字符串
* @param {Object} options 配置参数
* @example options = {
* stroke:"#FF0000",
* strokeWidth: 1.0,
* strokeOpacity: 1.0,
* strokeLineJoin: "bevel",
* strokeLineCap: "square",
* strokeDashArray:"Dash Line",// Dash Line、Solid Line、Dot Line、Dash Dot Line、Dash Dot Dot Line、Dash Dot Dot Line、或者满足cssstroke-dasharray的字符串如"6 4"
* perpendicularOffset: 0.0
* }
*/
createLineSymbol: (options) => {
const createDashArray = (lineType) => {
if (!lineType) return "";
if (lineType instanceof Array) return lineType.join(" ");
switch (lineType) {
case "Dash Line":
return "6 6";
case "Solid Line":
return "";
case "Dot Line":
return "4 4";
case "Dash Dot Line":
return "8 4 4 4";
case "Dash Dot Dot Line":
return "8 4 4 4 4";
default:
return lineType;
}
};
return `<LineSymbolizer>
<Stroke>
<CssParameter name="stroke">${options.stroke || "#333333"}</CssParameter>
<CssParameter name="stroke-width">${options.strokeWidth || 1.0}</CssParameter>
<CssParameter name="stroke-opacity">${options.strokeOpacity || 1.0}</CssParameter>
<CssParameter name="stroke-linejoin">${options.strokeLineJoin || "bevel"}</CssParameter>
<CssParameter name="stroke-linecap">${options.strokeLineCap || "square"}</CssParameter>
<CssParameter name="stroke-dasharray">${createDashArray(options.strokeDashArray)}</CssParameter>
</Stroke>
<PerpendicularOffset>${options.perpendicularOffset || 0.0}</PerpendicularOffset>
</LineSymbolizer>`;
},
/**
* 创建面符号的XML格式的字符串
* @param {Object} options 配置参数
* @example options = {
* fill:"#FF0000",
* fillOpacity: 0.5,
* stroke:"#FF0000",
* strokeWidth: 1.0,
* strokeOpacity: 1.0,
* }
*/
createPolygonSymbol: (options) => {
return `<PolygonSymbolizer>
<Fill>
<CssParameter name="fill">${options.fill || "#333333"}</CssParameter>
<CssParameter name="fill-opacity">${options.fillOpacity || 1.0}</CssParameter>
</Fill>
<Stroke>
<CssParameter name="stroke">${options.stroke || "#333333"}</CssParameter>
<CssParameter name="stroke-width">${options.strokeWidth || 1.0}</CssParameter>
<CssParameter name="stroke-opacity">${options.strokeOpacity || 1.0}</CssParameter>
</Stroke>
</PolygonSymbolizer>`;
},
/**
* 创建注记符号的XML格式的字符串
* @param {Object} options 标签选项
* @example options = {
* fill:"#FF0000",
* fillOpacity: 0.5,
* anchorPointX:"#FF0000",
* anchorPointY: 1.0,
* displacementX: 1.0,
* displacementY: 1.0,
* autoWrap: autoWrap,
* rotation: 0,
* group: 100,
* perpendicularOffset: 0,
* propertyName: "dia",
* fontFamily: "fontFamily",
* fontSize: 12,
* }
* @param {String} geomType 类型Point、Line、Polygon
* @returns String
*/
createLabelSymbol: (options, geomType) => {
if (!options.propertyName) { throw Error(`×××××××× Invalid property: 文字注记的规则必须指定propertyName`); }
const LinePlacement = `<LinePlacement>
<PerpendicularOffset>${options.perpendicularOffset || 0.0}</PerpendicularOffset>
</LinePlacement>`;
const PointPlacement = `<PointPlacement>
<AnchorPoint><AnchorPointX>${options.anchorPointX || 0.5}</AnchorPointX><AnchorPointY>${options.anchorPointY || 0.5}</AnchorPointY></AnchorPoint>
<Displacement><DisplacementX>${options.displacementX || 0.0}</DisplacementX><DisplacementY>${options.displacementY || 0.0}</DisplacementY></Displacement>
<Rotation>${options.rotation || 0.0}</Rotation>
</PointPlacement>`;
const placement = geomType === "Line" ? LinePlacement : PointPlacement;
return `<TextSymbolizer>
<Label>
<ogc:PropertyName>${options.propertyName}</ogc:PropertyName>
</Label>
<Font>
<CssParameter name="font-family">${options.fontFamily || "Open Sans"}</CssParameter>
<CssParameter name="font-size">${options.fontSize || 12}</CssParameter>
</Font>
<LabelPlacement>
${placement}
</LabelPlacement>
<Fill>
<CssParameter name="fill">${options.fill || "#333333"}</CssParameter>
</Fill>
<VendorOption name="autoWrap">${options.autoWrap || 100}</VendorOption>
<VendorOption name="group">${options.group || "yes"}</VendorOption>
</TextSymbolizer>`;
}
};