lg_frontend/static/libs/mars3d/thirdParty/pbf-ol/style/TaitanPbfStyle.js

336 lines
11 KiB
JavaScript
Raw Permalink Normal View History

//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)