wangbd-myui
Version:
MY前端基础框架核心组件库
173 lines (170 loc) • 4.66 kB
JavaScript
/**
* 轨迹组件
* @module $ui/map/my-map-track
*/
import MapLine from '../my-map-line'
import parseStyle from '../../utils/style'
import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
const defaultEffect = {
circle: {
fill: '#409eff',
radius: 6
}
}
export default {
name: 'MyMapTrack',
mixins: [MapLine],
/**
* 属性参数,继承 [$ui/map/my-map-line]{@link module:$ui/map/my-map-line}
* @member props
* @property {boolean} [auto=true] 自动播放
* @property {boolean} [loop=true] 动画循环
* @property {string|object|function} [effect] 动画样式配置,字符串配置图片,object配置样式描述对象,function返回Style
* @property {number} [period=10] 动画周期,单位:秒
* @property {boolean} [pause] 暂停
*/
props: {
// 自动播放
auto: {
type: Boolean,
default: true
},
// 循环
loop: {
type: Boolean,
default: true
},
// 轨迹样式
effect: {
type: [Object, String, Function],
default() {
return defaultEffect
}
},
// 动画时间,秒
period: {
type: Number,
default: 10
},
// 暂停
pause: Boolean
},
data() {
return {
fraction: 0
}
},
methods: {
createEffectStyle(rotation) {
if (!this.effect) return null
const paramType = typeof this.effect
let styles = []
switch (paramType) {
case 'function':
styles = styles.concat(this.effect(this, rotation))
break
case 'object':
styles.push(parseStyle(this.effect))
break
case 'string':
styles.push(parseStyle({
icon: {
src: this.effect,
rotateWithView: false,
rotation: -rotation,
scale: 0.5
}
}))
break
}
return styles
},
getRotation(prev, next) {
const dx = prev[0] - next[0]
const dy = prev[1] - next[1]
return Math.atan2(dy, dx)
},
effectRender() {
if (!this.feature) return
const geometry = this.feature.getGeometry()
const coordinates = geometry.getCoordinates()
if (!coordinates || coordinates.length === 0) return
if (!this.effectFeature) {
this.effectFeature = new Feature(new Point(coordinates[0]))
this.myMap.addFeature(this.effectFeature)
}
/**
* 动画开始时触发
* @event start
* @param {VueComponent} vm
*/
this.$emit('start', this)
const {effectFeature, period} = this
const start = new Date().getTime()
const animate = () => {
const tick = new Date().getTime()
let fraction = (tick - start) / (period * 1000)
fraction += this.fraction
if (fraction > 1) {
/**
* 动画完成时触发
* @event finish
* @param {VueComponent} vm
*/
this.$emit('finish', this)
this.fraction = 0
if (this.loop) {
this.effectRender()
} else {
/**
* 动画停止时触发
* @event stop
* @param {VueComponent} vm
*/
this.$emit('stop', this)
}
return
}
const coordinate = geometry.getCoordinateAt(fraction)
const nextCoordinate = geometry.getCoordinateAt(Math.min(fraction + 0.0001, 1))
const rotation = this.getRotation(coordinate, nextCoordinate)
effectFeature.getGeometry().setCoordinates(coordinate)
effectFeature.setStyle(this.createEffectStyle(rotation))
if (this.pause) {
this.fraction = fraction
} else {
this.$emit('move', coordinate, rotation)
this.aId = window.requestAnimationFrame(animate)
}
}
animate()
},
start() {
this.fraction = 0
this.effectRender()
},
stop() {
this.aId && window.cancelAnimationFrame(this.aId)
}
},
watch: {
pause(val) {
if (!val) {
this.effectRender()
}
}
},
created() {
if (this.auto && !this.pause) {
this.$on('feature-draw', this.effectRender)
}
},
beforeDestroy() {
if (this.effectFeature) {
this.myMap.removeFeature(this.effectFeature)
}
this.aId && window.cancelAnimationFrame(this.aId)
this.$off('feature-draw', this.effectRender)
}
}