//taitan公司自定义的Sld 样式 //sld与mvt样式区别:sld针对一个要素多个rule的样式可以同时独立生效,而mvt只能给一个要素设置一个样式 ;(function (window) { function TaitanPbfStyle(options) { this.ol = null this.json = {} this.options = {} this.style = {} this.iconCache = {} this.properties = null this.type = null this.scale = null this.resolution = null this.filterIsPass = null this.scaleIsPass = true this.init(options) } TaitanPbfStyle.prototype = { constructor: TaitanPbfStyle, defaults: { ol: null, json: {}, }, init: function (options) { let opts = Object.assign({}, this.defaults, options) this.json = opts.json this.ol = opts.ol }, reset: function () { this.options = {} this.style = {} this.properties = null this.type = null this.scale = null this.resolution = null this.filterIsPass = null this.scaleIsPass = true }, getStyle: function () { let This = this return function (feature, resolution) { This.reset() This.type = feature.getGeometry().getType() This.properties = feature.getProperties() This.resolution = resolution This.scale = 1 / (0.0254 / (96 * resolution)) This.filter() return This.buildStyle() } }, // 根据options组装最终的样式对象 buildStyle: function () { if (Object.keys(this.options).length == 0) return [new this.ol.style.Style({})] // if (JSON.stringify(this.options) == '{}') return; // 组装基础样式 switch (this.type.toLowerCase()) { case 'point': if (this.options.image.imageStyle) this.style.image = this.options.image.imageStyle break case 'linestring': if (this.options.stroke) this.style.stroke = this.options.stroke break case 'polygon': if (this.options.fill) this.style.fill = this.options.fill if (this.options.stroke) this.style.stroke = this.options.stroke break default: break } // 组装label样式,这里控制了下显示层级,只有分辨率小于40的时候才会显示label,后续可以做成可配置项 if (this.resolution < 40 && this.options.text) { this.style.text = new this.ol.style.Text({ text: this.options.text.text ? this.options.text.text + '' : '', textBaseline: 'top', overflow: 'line', font: `${this.options.text.font || 10}px sans-serif`, offsetX: this.options.text.offsetX, offsetY: this.options.text.offsetY, fill: this.options.text.fill, stroke: this.options.text.stroke, rotateWithView: false, }) } // 组装层级样式 this.style.zIndex = this.options.zIndex || 1 return [new this.ol.style.Style(this.style)] }, // 构建样式options buildOptions: function (rule) { // rule.Symbolizer.WellKnownName = 'img'; // rule.Symbolizer.src = 'https://unpkg.com/@mapbox/maki@4.0.0/icons/park-15.svg'; this.options.image = {} this.options.image.rotation = rule.Symbolizer.Rotation || 0 if (rule.Symbolizer.FillColor && rule.Symbolizer.WellKnownName != 'img') { let imgFillColor = this.buildRgba(rule.Symbolizer.FillColor, rule.Symbolizer.FillOpacity) this.options.image.fill = new this.ol.style.Fill({ color: imgFillColor, }) if (rule.Symbolizer.StrokeColor) { let imgStrokeColor = this.buildRgba(rule.Symbolizer.StrokeColor, rule.Symbolizer.StrokeOpacity) this.options.image.stroke = new this.ol.style.Stroke({ color: imgStrokeColor, width: rule.Symbolizer.StrokeWidth, lineDash: rule.Symbolizer.StrokeDasharray.split(' '), }) } } this.options.image.render = 'image' switch (rule.Symbolizer.WellKnownName) { case 'circle': // 圆形 this.options.image.radius = rule.Symbolizer.Size this.options.image.imageStyle = new this.ol.style.Circle(this.options.image) break case 'square': // 正方形 this.options.image.radius = rule.Symbolizer.Size this.options.image.points = 4 this.options.image.angle = Math.PI / 4 this.options.image.imageStyle = new this.ol.style.RegularShape(this.options.image) break case 'triangle': // 三角形 this.options.image.radius = rule.Symbolizer.Size this.options.image.points = 3 this.options.image.angle = 0 this.options.image.imageStyle = new this.ol.style.RegularShape(this.options.image) break case 'star': // 五角形 this.options.image.radius = rule.Symbolizer.Size this.options.image.points = 5 this.options.image.radius2 = rule.Symbolizer.Size / 2.5 this.options.image.angle = 0 this.options.image.imageStyle = new this.ol.style.RegularShape(this.options.image) break case 'cross': // 十字架 this.options.image.radius = rule.Symbolizer.Size this.options.image.points = 4 this.options.image.radius2 = 0 this.options.image.angle = 0 this.options.image.imageStyle = new this.ol.style.RegularShape(this.options.image) break case 'x': // ×形 this.options.image.radius = rule.Symbolizer.Size this.options.image.points = 4 this.options.image.radius2 = 0 this.options.image.angle = Math.PI / 4 this.options.image.imageStyle = new this.ol.style.RegularShape(this.options.image) break case 'img': let icon = this.iconCache[rule.Symbolizer.src] if (!icon) { this.options.image.src = rule.Symbolizer.src this.options.image.anchorXUnits = 'fraction' this.options.image.anchorYUnits = 'fraction' this.options.image.anchor = [0.5, 0.5] this.options.image.offset = [0, 0] this.options.image.scale = 1 this.options.image.rotation = rule.Symbolizer.Rotation ;(this.options.image.crossOrigin = 'anonymous'), (this.options.image.imageStyle = new this.ol.style.Icon(this.options.image)) this.iconCache[rule.Symbolizer.src] = this.options.image.imageStyle } else { this.options.image.imageStyle = icon } break default: break } // 构建option中的填充色 if (rule.Symbolizer.FillColor) { let fillColor = this.buildRgba(rule.Symbolizer.FillColor, rule.Symbolizer.FillOpacity) this.options.fill = new this.ol.style.Fill({ color: fillColor, }) } // 构建option中的边框 let strokeColor, strokeWidth, strokeDasharray if (rule.Symbolizer.StrokeColor) { strokeColor = this.buildRgba(rule.Symbolizer.StrokeColor, rule.Symbolizer.StrokeOpacity) if (rule.Symbolizer.StrokeWidth && rule.Symbolizer.StrokeWidth > 1) { strokeWidth = rule.Symbolizer.StrokeWidth } if (rule.Symbolizer.StrokeDasharray && rule.Symbolizer.StrokeDasharray.split(' ')) { strokeDasharray = rule.Symbolizer.StrokeDasharray.split(' ') } this.options.stroke = new this.ol.style.Stroke({ color: strokeColor, width: strokeWidth, lineDash: strokeDasharray, }) } // 构建option中的标签 if (rule.Label && JSON.stringify(rule.Label) != '{}') { this.options.text = {} this.options.text.text = this.properties[rule.Label.PropertyName] this.options.text.font = rule.Label.FontSize this.options.text.offsetX = rule.Label.AnchorPointX this.options.text.offsetY = rule.Label.AnchorPointY if (rule.Label.FillColor) { let fillColor = this.buildRgba(rule.Label.FillColor, rule.Label.FillOpacity) this.options.text.fill = new this.ol.style.Fill({ color: fillColor, }) } if (rule.Label.HaloFillColor) { let haloFillColor = this.buildRgba(rule.Label.HaloFillColor, rule.Label.HaloFillOpacity) this.options.text.stroke = new this.ol.style.Stroke({ color: haloFillColor, width: rule.Label.HaloRadius, }) } } }, // 根据属性和比例条件进行判断 filter: function () { for (let rule of this.json.Rule) { // 每次循环开始前将重置filterIsPass参数 this.filterIsPass = undefined // 判断属性过滤条件,如果属性过滤条件参数不存在或者为空,则不做进一步的判断,直接赋值true if ( rule.Filter instanceof Object == false || JSON.stringify(rule.Filter) == '{}' || rule.Filter.Conditions == undefined || rule.Filter.Conditions.length == 0 ) { this.filterIsPass = true } else { this.filterConditions(rule.Filter) } this.buildOptions(rule) // 判断比例条件是否符合 // let minScale = rule.MinScaleDenominator ? rule.MinScaleDenominator : 10; // let maxScale = rule.MaxScaleDenominator ? rule.MaxScaleDenominator : 10000000000; // this.scaleIsPass = (this.scale < minScale || this.scale > maxScale) ? false : true; // if (this.filterIsPass && this.scaleIsPass) this.buildOptions(rule); } }, // 根据属性过滤条件进行判断 filterConditions: function (filter) { for (let condition of filter.Conditions) { let bool, val = this.properties[condition.PropertyName] + '' || '' switch (condition.Condition) { case 'PropertyIsEqualTo': bool = val == condition.Literal break case 'PropertyIsNotEqualTo': bool = val != condition.Literal break case 'PropertyIsLike': bool = val.indexOf(condition.Literal) > -1 break case 'PropertyIsBetween': let num = parseFloat(val) bool = num >= condition.LowerBoundary.Literal && num <= condition.UpperBoundary.Literal break default: break } if (filter.FilterType == 'And') { this.filterIsPass = this.filterIsPass == undefined ? bool : this.filterIsPass && bool } else if (filter.FilterType == 'Or') { this.filterIsPass = this.filterIsPass == undefined ? bool : this.filterIsPass || bool } } }, hexToRgb: function (hex) { let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16), } : null }, buildRgba: function (hex, opa) { hex = this.hexToRgb(hex) if (hex == 'null') return '' return `rgba(${hex.r},${hex.g},${hex.b},${opa})` }, } //对外接口 window.mars3d.TaitanPbfStyle = TaitanPbfStyle })(window)