function MapMaker() {
|
// 非连续坐标点最大距离(米)
|
this.maxD = 500;
|
// 当前绘制的监测因子类型
|
this.factorType = 0;
|
this.factorDatas
|
// 载具类型
|
this.vehicleType = 0 // 0: 车辆;1:无人机:2:无人船
|
// 帧动画控制工具
|
this.frameAnimation = new FrameAnimation();
|
// 动画帧数
|
this._fps = this.frameAnimation.fps;
|
// 绘制图形缓存
|
this.moveViews = {};
|
}
|
|
MapMaker.prototype = {
|
setFactorType: function (factorType) {
|
this.factorType = factorType;
|
},
|
|
/**
|
* 设置载具类型,对应显示不同的图标
|
*/
|
setVehicleType: function (t) {
|
this.vehicleType = t
|
this.moveViews = {}
|
},
|
|
/**
|
* 车辆移动动画
|
* @param {*} factorDatas
|
* @param {*} factorType
|
*/
|
moveAnimation: function (factorDatas, factorType, startIndex) {
|
// MapUtil.drawLine(factorDatas.lnglats_GD)
|
|
// 设置当前数据的最新时间
|
this.frameAnimation.lastestTime = factorDatas.times[factorDatas.times.length - 1]
|
|
// 当数据缓存不为空时,说明上一次的绘制还未结束,所以只更新数据源即可
|
if (this.factorDatas != undefined) {
|
this.factorType = factorType;
|
this.factorDatas = factorDatas;
|
return
|
}
|
|
this.factorType = factorType;
|
this.factorDatas = factorDatas;
|
|
this.startIndex = startIndex == undefined ? 0 : startIndex;
|
// 一次性最多计算[this.frameAnimation.maxTasks]个坐标点的绘制轨迹,绘制完成后再次计算,提升前端网页响应速度
|
this.endIndex = this.startIndex + this.frameAnimation.maxTasks
|
if (this.endIndex >= factorDatas.length()) {
|
this.endIndex = factorDatas.length() - 1
|
}
|
|
// console.log(new Date());
|
this.nextAnimation(this.startIndex, factorDatas, this.endIndex)
|
// console.log(new Date());
|
},
|
|
nextAnimation: function (start, factorDatas, endIndex) {
|
if (factorDatas == undefined) {
|
return
|
}
|
var that = this;
|
|
// 数据格式转换
|
for (let i = start; i < factorDatas.length(); i++) {
|
// 终点
|
if (i == endIndex || i == factorDatas.length() - 1) {
|
break;
|
}
|
// 动画轨迹
|
var animationData = factorDatas.getByIndex(0, i + 1);
|
|
// 路径点
|
var sPos = factorDatas.lnglats_GD[i];
|
var ePos = factorDatas.lnglats_GD[i + 1];
|
// 终点相对起点的角度
|
var angle = this._getAngle(sPos, ePos);
|
// 路径总长度
|
var distance = AMap.GeometryUtil.distance(sPos, ePos);
|
|
// 时间差
|
var d1 = new Date(factorDatas.times[i]);
|
var d2 = new Date(factorDatas.times[i + 1]);
|
var duration = (d2 - d1) / 1000;
|
// 总帧数
|
var count = duration * this._fps;
|
// 单帧距离
|
var d = distance / count;
|
// 每个fps对应的实际时长(默认1秒)
|
var t = 1;
|
// 两点间不连续时
|
if (distance > this.maxD) {
|
count = 4 * this._fps;
|
d = distance / count;
|
t = duration / (count / this._fps);
|
}
|
|
// 监测数据
|
// var fData1 = factorDatas.getByIndex(i, i + 1)
|
var fData2 = factorDatas.getByIndex(i + 1, i + 2);
|
|
// 计算动画轨迹
|
for (let i = 0; i < count - 1; i++) {
|
// path
|
var length = d * (i + 1);
|
if (isNaN(angle)) {
|
animationData.lnglats_GD.push(sPos);
|
} else {
|
var point = this._getLatLon(sPos, length, angle);
|
animationData.lnglats_GD.push(point);
|
}
|
// time
|
var time = d1.format("yyyy-MM-dd hh:mm:ss");
|
if ((i + 1) % this._fps == 0) {
|
var t1 = d1.getTime();
|
d1.setTime(t1 + t * 1000);
|
time = d1.format("yyyy-MM-dd hh:mm:ss");
|
}
|
animationData.times.push(time);
|
}
|
// factor
|
for (const key in animationData.factor) {
|
var factor = animationData.factor[key];
|
factor.insertFrame(fData2.factor[key], count, distance <= this.maxD);
|
}
|
|
animationData.refreshHeight();
|
var coor_GD = MapUtil.lngLatToGeodeticCoord(animationData.lnglats_GD);
|
animationData.coors_GD = coor_GD;
|
|
this.frameAnimation.addTask(count, animationData, function (data, index, count) {
|
var length = data.length();
|
var start = length - count + 1;
|
// 1.获取数据
|
var d = data.getByIndex(0, start + index + 1);
|
var f = d.factor[that.factorType + 1 + ""];
|
// 2.绘制图形
|
if (length > count || index > 0) {
|
// 3d图形
|
var lnglat = d.lnglats_GD[d.lnglats_GD.length - 1];
|
MapUtil.drawMesh2(
|
d.lnglats_GD,
|
d.coors_GD,
|
f.heights,
|
f.colors,
|
f.bottomColor
|
);
|
// MapUtil.drawLine(lnglat)
|
|
// 风向风速
|
if (d.factor['17'] != undefined && d.factor['16'] != undefined) {
|
var windDir = d.factor["17"].datas;
|
windDir = windDir[windDir.length - 1].factorData;
|
var windSpeed = d.factor["16"].datas;
|
windSpeed = windSpeed[windSpeed.length - 1].factorData;
|
MapUtil.drawSector3(lnglat, windDir, windSpeed);
|
}
|
}
|
|
var pos = d.lnglats_GD[d.lnglats_GD.length - 1];
|
var time = d.times[d.times.length - 1].slice(10);
|
// 绘制车辆图标和时间文本
|
var status = 0;
|
// 停止
|
if (index + 1 == count) {
|
status = 1;
|
}
|
// 行驶中
|
else {
|
status = 2;
|
}
|
that._setPosition(pos, time, status);
|
// console.log("animation");
|
}
|
);
|
}
|
|
// 当endIndex已经是最后一个坐标点时,路径绘制结束,否则开始下一段路径绘制
|
if (that.endIndex < that.factorDatas.length() - 1) {
|
that.startIndex = that.endIndex
|
that.endIndex = that.startIndex + that.frameAnimation.maxTasks
|
if (that.endIndex >= that.factorDatas.length) {
|
that.endIndex = that.factorDatas.length - 1
|
}
|
var cb = function () {
|
that.nextAnimation(that.startIndex, that.factorDatas, that.endIndex)
|
}
|
that.frameAnimation.addOnNextTasks(cb)
|
}
|
// 当全部数据绘制完成时,清空数据
|
else {
|
that.factorDatas = undefined
|
that.frameAnimation.addOnNextTasks(undefined)
|
}
|
|
this.start();
|
},
|
|
/*******************************动画任务逻辑 -start ******************************/
|
start: function () {
|
this.frameAnimation.start();
|
},
|
changeSpeed: function (speed) {
|
this.frameAnimation.changeSpeed(speed);
|
},
|
pause: function () {
|
this.frameAnimation.pause();
|
},
|
stop: function () {
|
this.factorDatas = undefined
|
this.frameAnimation.addOnNextTasks(undefined)
|
this.frameAnimation.stop();
|
},
|
setOnStopCallback: function (callback) {
|
this.frameAnimation.setOnStopCallback(
|
function () {
|
this._clearMap()
|
callback();
|
}.bind(this)
|
);
|
},
|
runStatus: function () {
|
return this.frameAnimation.runStatus();
|
},
|
/**
|
* 设置是否开启动态绘制速度
|
*/
|
setDynamicSpeed: function (b, sec) {
|
if (b) {
|
this.frameAnimation.dynamicSpeed = true
|
this.frameAnimation.taskPeriod = sec
|
} else {
|
this.frameAnimation.dynamicSpeed = false
|
this.frameAnimation.taskPeriod = sec
|
}
|
},
|
/*******************************动画任务逻辑 -end ******************************/
|
|
_clearMap: function () {
|
var list = [];
|
for (const key in this.moveViews) {
|
list.push(this.moveViews[key]);
|
}
|
MapUtil.removeViews(list);
|
this.moveViews = {};
|
MapUtil.clearSector3()
|
},
|
_setPosition: function (pos, time, status) {
|
var lnglat = new AMap.LngLat(...pos);
|
if (this.moveViews["text"] == undefined) {
|
var url
|
switch (this.vehicleType) {
|
case 0:
|
url = "./asset/mipmap/car_driving.png";
|
break;
|
case 1:
|
url = "./asset/mipmap/car_driving.png";
|
break;
|
case 2:
|
url = "./asset/mipmap/boat_driving.png";
|
break;
|
default:
|
url = "./asset/mipmap/car_driving.png";
|
break;
|
}
|
// var url = "./asset/mipmap/car_offline.png";
|
// switch (status) {
|
// case 0:
|
// url = "./asset/mipmap/car_offline.png";
|
// break;
|
// case 1:
|
// url = "./asset/mipmap/car_stop.png";
|
// break;
|
// case 2:
|
// url = "./asset/mipmap/car_driving.png";
|
// break;
|
// default:
|
// url = "./asset/mipmap/car_stop.png";
|
// break;
|
// }
|
|
var icon = new AMap.Icon({
|
size: new AMap.Size(60, 30),
|
imageSize: new AMap.Size(54, 21),
|
image: url,
|
// imageOffset: new AMap.Pixel(-16, -16) // 相对于基点的偏移位置
|
});
|
|
var car = new AMap.Marker({
|
icon: icon,
|
position: lnglat, // 基点位置
|
offset: new AMap.Pixel(-20, -15), // 相对于基点的偏移位置
|
});
|
|
MapUtil._map.add(car);
|
this.moveViews["car"] = car;
|
|
// 时间
|
var text = new AMap.Text({
|
text: time,
|
position: lnglat,
|
offset: new AMap.Pixel(0, 30),
|
});
|
MapUtil._map.add(text);
|
this.moveViews["text"] = text;
|
} else {
|
MapUtil.setCenter(lnglat);
|
this.moveViews["car"].setPosition(lnglat);
|
this.moveViews["text"].setPosition(lnglat);
|
this.moveViews["text"].setText(time);
|
}
|
},
|
_setStatus: function (status) {},
|
|
/**
|
* 根据坐标点、距离和角度,得到另一个坐标点
|
* @param {*} pos
|
* @param {*} distance 米
|
* @param {*} angle
|
*/
|
_getLatLon: function (pos, distance, angle) {
|
var Ea = 6378137; // 赤道半径
|
var Eb = 6356725; // 极半径
|
var dx = distance * Math.sin((angle * Math.PI) / 180);
|
var dy = distance * Math.cos((angle * Math.PI) / 180);
|
var ec = Eb + ((Ea - Eb) * (90.0 - pos[1])) / 90.0;
|
var ed = ec * Math.cos((pos[1] * Math.PI) / 180);
|
var lng = ((dx / ed + (pos[0] * Math.PI) / 180.0) * 180.0) / Math.PI;
|
var lat = ((dy / ec + (pos[1] * Math.PI) / 180.0) * 180.0) / Math.PI;
|
return [lng, lat];
|
},
|
|
/**
|
* 根据两个坐标点获得相对角度
|
* @param {*} sPos
|
* @param {*} ePos
|
*/
|
_getAngle: function (sPos, ePos) {
|
var lng_a = sPos[0];
|
var lat_a = sPos[1];
|
var lng_b = ePos[0];
|
var lat_b = ePos[1];
|
|
var a = ((90 - lat_b) * Math.PI) / 180;
|
var b = ((90 - lat_a) * Math.PI) / 180;
|
var AOC_BOC = ((lng_b - lng_a) * Math.PI) / 180;
|
var cosc =
|
Math.cos(a) * Math.cos(b) + Math.sin(a) * Math.sin(b) * Math.cos(AOC_BOC);
|
var sinc = Math.sqrt(1 - cosc * cosc);
|
var sinA = (Math.sin(a) * Math.sin(AOC_BOC)) / sinc;
|
var A = (Math.asin(sinA) * 180) / Math.PI;
|
var res = 0;
|
if (lng_b > lng_a && lat_b > lat_a) res = A;
|
else if (lng_b > lng_a && lat_b < lat_a) res = 180 - A;
|
else if (lng_b < lng_a && lat_b < lat_a) res = 180 - A;
|
else if (lng_b < lng_a && lat_b > lat_a) res = 360 + A;
|
else if (lng_b > lng_a && lat_b == lat_a) res = 90;
|
else if (lng_b < lng_a && lat_b == lat_a) res = 270;
|
else if (lng_b == lng_a && lat_b > lat_a) res = 0;
|
else if (lng_b == lng_a && lat_b < lat_a) res = 180;
|
|
return res;
|
},
|
};
|