wangbd-myui
Version:
MY前端基础框架核心组件库
242 lines (238 loc) • 7.59 kB
JavaScript
/**
* Flight 航线组件
* @module $ui/map/my-map-flight
*/
import strokeMixin from '../../mixins/stroke'
import featureMixin from '../../mixins/feature'
import LineString from 'ol/geom/LineString'
import Point from 'ol/geom/Point'
import Feature from 'ol/Feature'
import {createCurvePoints, createLinePathPoints, coordinateEqual} from '../../utils/util'
import createArrow from '../../utils/arrow'
import parseStyle from '../../utils/style'
// 默认线动效样式
const defaultLineEffect = {
color: '#409eff',
lineDash: null
}
// 默认点动效样式
const defaultPointEffect = {
circle: {
fill: '#409eff',
radius: 3
}
}
/**
* 属性参数, 继承 [$ui/map/mixins/feature]{@link module:$ui/map/mixins/feature}
* @member props
* @property {number[]} from 起点
* @property {number[]} to 终点
* @property {number} [radius=0] 曲线半径度数, 默认为0,直线
* @property {number} [angle=90] 曲线角度,radius与 angle结合可定义曲线的形状
* @property {string|boolean|object} [arrow] 终点箭头
* @property {string} [color] 颜色
* @property {number} [width] 线条宽度
* @property {string} [lineCap]
* @property {string} [lineJoin]
* @property {number[]} [lineDash]
* @property {number} [lineDashOffset]
* @property {number} [delay] 动画延时开始
* @property {boolean} [loop] 动画循环
* @property {number} [space=0.01] 分割点的距离,可通过改设置控制动画移动的速度,值越大速度越快
* @property {number} [smooth=0.01] 平滑度,越小线越平滑
* @property {boolean|object|function} [lineEffect=true] 线动画样式配置
* @property {boolean|object|function} [pointEffect=false] 点动画样式配置
*/
export default {
name: 'MyMapFlight',
mixins: [strokeMixin, featureMixin],
props: {
// 起点
from: Array,
// 终点
to: Array,
// 曲线半径度数
radius: {
type: Number,
default: 0
},
// 曲线角度
angle: {
type: Number,
default: 90
},
// 箭头
arrow: [Boolean, String, Object],
delay: {
type: Number,
default: 0
},
loop: {
type: Boolean,
default: true
},
space: {
type: Number,
default: 0.01
},
// 平滑度,越小线越平滑
smooth: {
type: Number,
default: 0.01
},
color: {
type: String,
default: 'rgba(64, 158, 255, 0.5)'
},
lineDash: {
type: Array,
default() {
return [5]
}
},
lineEffect: {
type: [Boolean, Object, Function],
default() {
return defaultLineEffect
}
},
pointEffect: {
type: [Boolean, Object, Function],
default: false
}
},
methods: {
createPoints() {
const line = this.radius > 0
? createCurvePoints(this.from, this.to, this.radius, this.angle, this.smooth)
: [this.from, this.to]
return this.space ? createLinePathPoints(line, this.space) : line
},
drawHandler() {
const points = this.createPoints()
return new LineString(points)
},
modifyHandler(geometry) {
geometry.setCoordinates(this.createPoints())
},
createArrowStyle(coordinates, strokeProps = {}) {
const length = coordinates.length
let index = 0
const to = coordinates[length - 1]
let from = to
while (from && coordinateEqual(from, to)) {
++index
from = coordinates[length - index]
}
return createArrow(from || to, to, this.arrow, {color: strokeProps.color || this.color})
},
createLineEffectStyle(feature, strokeProps = {}) {
const styles = this.createLineStyle(strokeMixin.props, strokeProps)
const coordinates = feature.getGeometry().getCoordinates()
if (this.arrow) {
const arrowStyle = this.createArrowStyle(coordinates, strokeProps)
styles.push(arrowStyle)
}
return styles
},
createPointEffectStyle(feature, pointEffect) {
if (!this.pointEffect) return null
return parseStyle({
...defaultPointEffect,
...pointEffect
})
},
setStyle() {
if (!this.feature) return
const style = this.createLineEffectStyle(this.feature)
this.feature.setStyle(style)
this.lineEffect && this.lineDelayStart(this.lineEffectRender)
this.pointEffect && this.pointDelayStart(this.pointEffectRender)
},
lineEffectRender() {
const geometry = this.feature.getGeometry()
const coordinates = geometry.getCoordinates()
const length = coordinates.length
if (!this.lineEffectFeature) {
this.lineEffectFeature = new Feature(new LineString([coordinates[0]]))
this.myMap.addFeature(this.lineEffectFeature)
}
const feature = this.lineEffectFeature
let fraction = 0
// eslint-disable-next-line no-unused-vars
const animate = () => {
++fraction
if (fraction > length) {
this.loop && this.lineEffectRender()
return
}
const points = coordinates.slice(0, fraction + 1)
const line = new LineString(points)
const style = typeof this.lineEffect === 'function'
? this.lineEffect({feature, fraction, points, line, vm: this})
: this.createLineEffectStyle(feature, {
...defaultLineEffect,
...this.lineEffect
})
feature.setGeometry(line)
feature.setStyle(style)
window.requestAnimationFrame(animate)
}
animate()
},
pointEffectRender() {
const geometry = this.feature.getGeometry()
const coordinates = geometry.getCoordinates()
const length = coordinates.length - 1
if (!this.pointEffectFeature) {
this.pointEffectFeature = new Feature(new Point(coordinates[0]))
this.myMap.addFeature(this.pointEffectFeature)
}
const feature = this.pointEffectFeature
let fraction = 0
// eslint-disable-next-line no-unused-vars
const animate = () => {
++fraction
if (fraction > length) {
this.loop && this.pointEffectRender()
return
}
const coordinate = coordinates[fraction]
const point = new Point(coordinate)
const style = typeof this.pointEffect === 'function'
? this.pointEffect({feature, fraction, coordinates, coordinate, point, vm: this})
: this.createPointEffectStyle(feature, this.pointEffect)
feature.setGeometry(point)
feature.setStyle(style)
window.requestAnimationFrame(animate)
}
animate()
},
lineDelayStart(func) {
if (this.delay) {
clearTimeout(this.lineDelayId)
this.lineDelayId = setTimeout(func, this.delay)
} else {
func()
}
},
pointDelayStart(func) {
if (this.delay) {
clearTimeout(this.pointDelayId)
this.pointDelayId = setTimeout(func, this.delay)
} else {
func()
}
}
},
beforeDestroy() {
if (this.lineEffectFeature) {
this.myMap.removeFeature(this.lineEffectFeature)
}
if (this.pointEffectFeature) {
this.myMap.removeFeature(this.pointEffectFeature)
}
this.pointDelayId && clearTimeout(this.pointDelayId)
this.lineDelayId && clearTimeout(this.lineDelayId)
}
}