/* arcgis动画计算参数 * graphic 动画图形 * paths 动画轨迹路径 */ let animate = function(pointGraphic,paths,line){ this.line = line; this.timer = null; this.paths = paths; //路径 this.index = 0; //像素帧下标 this.speed = 60; //速度 this.status = 0; //状态 // 0 停止 // 1 运动 this._animate = []; //监听动画的事件集 this.pointGraphic = pointGraphic; //唯一像素图片 this.analysisPaths = []; //像素帧 this.init.apply(this,arguments); } animate.prototype = { // 初始化函数 init (param){ // 开始处理分析路径 this.analysisPath() }, // 开始动画 play (index){ debugger; if( this.status == 1 ){ return //禁止重复播放 } this.status = 1; index && ( this.index = index ) this.animate(); }, // 暂停动画 pause (){ this.status = 0; this.timer && clearTimeout(this.timer); this.timer = null; }, // 重置动画 reset (){ this.pause(); this.index = 0; this.moveGraphic(0) }, // 改变速度 setSpeed (level){ this.speed = level * 60; if( this.status === 1 ){ // 如果正在播放中 this.pause(); this.play(); } }, getSpeed (){ return this.speed / 60; }, /* 分析路径处理 * 将路径分为可置信的几个小段 */ analysisPath (){ var paths = this.paths; var analysisPaths = []; var len = this.speed; for( var i = 0 ; i < paths.length-1 ; i++ ){ var //获取经度 lon = paths[i][0], //获取纬度 lat = paths[i][1]; //开始计算差值 var _lon = (lon - paths[i+1][0])/len; var _lat = (lat - paths[i+1][1])/len; for( var i1 = 0 ; i1 < len; i1++ ){ analysisPaths.push([lon-_lon*i1,lat-_lat*i1]) } } // 将处理好的位置像素帧保存下来 this.analysisPaths = analysisPaths; }, /* 动画过程 * */ animate (){ // this.status = 1; this.timer = setTimeout(()=>{ // 如果运动状态被改为了0 则立即停止 if( this.status === 0 ){ return } this.moveGraphic(this.index++); this.createLine(); if( this.index < this.analysisPaths.length ){ this.animate(); } },1000 / this.speed) }, /** 将点移动到对应下标上 * */ moveGraphic (index){ var point = this.analysisPaths[index]; this.pointGraphic.geometry.x = point[0]; this.pointGraphic.geometry.y = point[1]; this.pointGraphic.geometry = this.pointGraphic.geometry.clone(); this._onAnimate(this); }, /** 渲染轨迹线 * */ createLine() { if( this.line ){ debugger; this.line.geometry.paths[0] = this.analysisPaths.slice(0,this.index); this.line.geometry = this.line.geometry.clone(); } }, _onAnimate (_this){ this._animate.forEach(( e )=>{ try{ e(_this) }catch(e){}; return ; }); }, onAnimate (fn){ if( typeof fn === 'function' ){ this._animate.push(fn); return { remove (){ var index = this._animate.find((e)=> { return e === fn }); this._animate.splice(index,1); } } } } } export default animate;
上面就是封装好的简单代码了 逻辑很简单 看看就能懂
然后上一个实际使用案例
<template> <div> <div class='taskNotes'> <!-- 头部 --> <div class='taskNotesHead'> <img :src='require("@/assets/img/Plan/drawLineMap/shebei.png")' /> <span>作业记录详细</span> </div> <!-- 作用身体 --> <div> <div class='taskInfo'> <div class='taskInfoModel'> <div class='taskName'>设备名称:</div> <div>1号无人喷药车</div> </div> <div class='taskInfoModel'> <div class='taskName'>作业面积:</div> <div>5.3亩</div> </div> <div class='taskInfoModel'> <div class='taskName'>作业类型:</div> <div>巡检</div> </div> <div class='taskInfoModel'> <div class='taskName'>总计耗时:</div> <div>15分钟</div> </div> <div class='taskInfoModel'> <div class='taskName'>开始时间:</div> <div>2020-10-25 10:35</div> </div> <div class='taskInfoModel'> <div class='taskName'>结束时间:</div> <div>2020-10-25 10:35</div> </div> </div> </div> <!-- 尾部 --> <!-- <div class='footor'> --> <!-- <div class='save'>预览</div> <div class='save'>加速</div> <div class='save'>重置</div> --> <!-- </div> --> </div> <!-- 控制界面 --> <div class='optControl'> <div> <el-slider v-model="index" @change='changeIndex' max='100'></el-slider> </div> <div class='controlBox'> <i class='el-icon-refresh-left' @click='reset'></i> <i class='el-icon-video-pause' style='color:red;' v-show='status==1' @click='pause'></i> <i class='el-icon-video-play' style='color:green;' v-show='status==0' @click='play'></i> <div class='speed' @click='changeSpeed'> x{{speed}} </div> </div> </div> </div> </template> <script> import animate from './js/arcgis_animate'; import { map3d } from 'jiankun_map' var paths = [[12623867.192992784,2654167.017123362],[12623833.202421965,2654103.115462072],[12623804.1249852,2654046.746480573],[12623777.953436079,2653990.4498262624],[12623752.896882452,2653938.944122552],[12623717.467376597,2653872.9993854314],[12623689.386448707,2653815.950333535],[12623665.734689742,2653756.7947267327],[12623658.737134164,2653685.932486681]]; paths.reverse(); export default { data() { return { index: 0, speed: 1, status: 0 } }, mounted (){ }, methods: { createAnimate (){ // 路线对象 这里也是自己封装的一个 实际上 就是创建一个线段对象 主要用来实现动画的路线渲染的 var lineGraphic = map3d.Util.createGraphic({ geometry : { type: "polyline", hasZ: false, hasM: true, paths: [[]], spatialReference: { wkid: 102100 } }, symbol : { type: "simple-line", color: "lightblue", width: "2px", style: "short-dot" } }); debugger; var layer = map3d.Util.addGraphic(lineGraphic,"liaoweizhong") // 几何对象 这里是用的我自己封装的方法集 实际上就是创建一个点Graphic var pointGraphic = map3d.Util.createImgPoint({ img: require("@/assets/img/Plan/biaoshi.png"), xy: paths[0], spatialReference: { wkid: 102100 } }); var layer = map3d.Util.addGraphic(pointGraphic,"liaoweizhong") // 创建点动画 this.animate = new animate(pointGraphic,paths,lineGraphic); this.animate.onAnimate((res)=>{ this.status = res.status; this.index = parseInt((res.index + 1) / res.analysisPaths.length * 100); if( this.index === 100 ){ this.pause(); } }) }, pause (){ this.status = 0 this.animate.pause(); }, play (){ if( this.index === 100 ) { this.reset(); } this.animate.play(); }, reset (){ this.animate.reset(); }, changeIndex (){ this.animate.index = parseInt(this.animate.analysisPaths.length * (this.index / 100)); this.animate.moveGraphic(this.animate.index); }, changeSpeed (){ var level = this.animate.getSpeed(); level++; if( level > 3 ){ level = 1; } this.animate.setSpeed(level); debugger; this.speed = level; } } } </script> <style scoped> .taskNotes { position: absolute; top: 50px; right: 15px; background: #00000080; width: 185px; border-radius: 6px; color: #fff; padding: 8px; } .taskNotesHead { padding-bottom: 8px; margin-bottom: 8px; } .taskNotesHead img { width: 12px; } .taskInfoModel { display: flex; padding: 6px 0px; } .taskInfo { color: #ffffff; } .taskName { width: 65px; flex-shrink: 0; } .footor { display: flex; justify-content: space-between; padding: 9px 0; font-size: 12px; margin-top: 10px; } .save { padding: 6px 12px; background: #35a24c; border-radius: 4px; color: #ffffff; font-size: 12px; cursor: pointer; } .close { padding: 6px 12px; background: #ffffff; border-radius: 4px; color: #4e4d4d; font-size: 12px; cursor: pointer; } .optControl { position:absolute; bottom: 5px; left: 50%; transform: translateX(-50%); width: 300px; padding: 15px; border-radius: 4px; background: #000000A8; color: #fff; } .controlBox { display: flex; justify-content: space-evenly; font-size: 22px; } .controlBox i { cursor: pointer; } .speed { font-size: 12px; border-radius: 50%; border: solid 2px #fff; padding: 0 0px; width: 21px; text-align: center; line-height: 18px; } </style>