实现成果:
->
->
->
插件
import 'leaflet-imageoverlay-rotated';
import 'leaflet-path-transform';
引入Map.js文件 import * as Map from '@/utils/map.js';
// ptSrc: 圆上某点(初始点);
// ptRotationCenter: 圆心点;
// angle: 旋转角度° -- [angle * M_PI / 180]:将角度换算为弧度
// 【注意】angle 逆时针为正,顺时针为负
export function rotatePoint(ptSrc, ptRotationCenter, angle) {
var a = ptRotationCenter.x;
var b = ptRotationCenter.y;
var x0 = ptSrc.x;
var y0 = ptSrc.y;
var rx = a + (x0 - a) * Math.cos(angle * Math.PI / 180) - (y0 - b) * Math.sin(angle * Math.PI / 180);
var ry = b + (x0 - a) * Math.sin(angle * Math.PI / 180) + (y0 - b) * Math.cos(angle * Math.PI / 180);
var json = { x: rx, y: ry };
return json;
}
// 获取两点之间中心点
export function getCenterLonLat(oneLon, oneLat, twoLon, twoLat) {
// oneLon:第一个点的经度;oneLat:第一个点的纬度;twoLon:第二个点的经度;twoLat:第二个点的纬度;
let aLon = 0, aLat = 0;
let bLon = Number(oneLon) - Number(twoLon);
let bLat = Number(oneLat) - Number(twoLat);
// Math.abs()绝对值
if (bLon > 0) {
aLon = Number(oneLon) - Math.abs(bLon) / 2;
} else {
aLon = Number(twoLon) - Math.abs(bLon) / 2;
}
if (bLat > 0) {
aLat = Number(oneLat) - Math.abs(bLat) / 2;
} else {
aLat = Number(twoLat) - Math.abs(bLat) / 2;
}
return [aLon, aLat];
}
export function calcAngle(start, end, eqMap) {
// 通过map 将起始点终止点经纬度坐标转容器坐标
const pStart = eqMap.latLngToContainerPoint(start);
const pEnd = eqMap.latLngToContainerPoint(end);
// 计算容器坐标点位
const diffX = pStart.x - pEnd.x;
const diffY = -(pStart.y - pEnd.y);
// 通过坐标计算角度 逆时针角度
let angle = 360 * Math.atan2(diffY, diffX) / (2 * Math.PI) + 90;
// 将逆时针角度转换成正角度
angle = angle < 0 ? -angle : 360 - angle;
return angle;
}
/**
* 根据一个经纬度及距离角度,算出另外一个经纬度
* @param {*} lng 经度 113.3960698
* @param {*} lat 纬度 22.941386
* @param {*} brng 方位角 45 ---- 正北方:000°或360° 正东方:090° 正南方:180° 正西方:270°
* @param {*} dist 90000距离(米)
*
* 1、角度转换为弧度公式:弧度=角度×(π ÷度180 )
* 2、弧度转换为角度公式: 角度=弧度×(180÷π)
*/
export function getLonAndLat(lng, lat, brng, dist) {
//大地坐标系资料WGS-84 长半径a=6378137 短半径b=6356752.3142 扁率f=1/298.2572236
var a = 6378137;
var b = 6356752.3142;
var f = 1 / 298.257223563;
var lon1 = lng * 1;
var lat1 = lat * 1;
var s = dist;
var alpha1 = brng * (Math.PI / 180)//mapNumberUtil.rad(brng);
var sinAlpha1 = Math.sin(alpha1);
var cosAlpha1 = Math.cos(alpha1);
//var tanU1 = (1 - f) * Math.tan(mapNumberUtil.rad(lat1));
var tanU1 = (1 - f) * Math.tan(lat1 * (Math.PI / 180));
var cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)), sinU1 = tanU1 * cosU1;
var sigma1 = Math.atan2(tanU1, cosAlpha1);
var sinAlpha = cosU1 * sinAlpha1;
var cosSqAlpha = 1 - sinAlpha * sinAlpha;
var uSq = cosSqAlpha * (a * a - b * b) / (b * b);
var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
var sigma = s / (b * A), sigmaP = 2 * Math.PI;
while (Math.abs(sigma - sigmaP) > 1e-12) {
var cos2SigmaM = Math.cos(2 * sigma1 + sigma);
var sinSigma = Math.sin(sigma);
var cosSigma = Math.cos(sigma);
var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
sigmaP = sigma;
sigma = s / (b * A) + deltaSigma;
}
var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
var lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
(1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
var lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
var L = lambda - (1 - C) * f * sinAlpha *
(sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
var revAz = Math.atan2(sinAlpha, -tmp); // final bearing
var lngLatObj = { lng: lon1 + L * (180 / Math.PI), lat: lat2 * (180 / Math.PI) }
return lngLatObj;
}
接口返回数据格式:
data: [{
"id": "ccbcd9bd09f049c382b515a568dbe98f",
"positionNo": null,
"positionName": null,
"coordinate": "89.282914,44.824844#89.282978,44.824844#89.282978,44.824930#89.282914,44.824930",
"chartType": null,
"overlays": "[{\"lng\":\"89.282914\",\"lat\":\"44.824844\"},{\"lng\":\"89.282978\",\"lat\":\"44.824844\"},{\"lng\":\"89.282978\",\"lat\":\"44.824930\"},{\"lng\":\"89.282914\",\"lat\":\"44.824930\"}]",
"signType": null,
"positionStatus": null,
"orgId": null,
"createTime": null,
"updateTime": null,
"createBy": null,
"updateBy": null,
"enableFlag": null,
"courseAngle": 180.0,
"centerPoint": "89.282946,44.824902",
"type": "0",
"areaId": "00f3e0f4f8d141cb944ccd82fd110019",
"diggerProjection": null,
"projectionCoordinates": null,
"excavatorVin": "YH202401121357039",
"centerPointProjection": null,
"loadPositionModel": "1",
"no": "YH57039",
"name": "YH57039",
"loadNo": null,
"loadName": null,
"signTime": null,
"mapId": null,
"radius": "5.12"
}]
渲染装载位
// 渲染装载位
renderLoadArea(data, flag) {
var shapes;
var tips = (data.type == 1 ? 装载位 + ':' : 待装位 + ':') + data.name;
var color;
var tatget = this.loadPositionLayerGroup;
// 就绪
data.type == 1 ? color = "#1ab394" : color = "#ED9D3B";
tips = tips + '(启用)';
var coordinates = mapUtil2d.getCoordinates(JSON.parse(data.overlays));
shapes = L.polygon(coordinates, {
color: color,
weight: 1,
transform: flag == 1 ? true : false,
draggable: flag == 1 ? true : false,
excavatorVin: data.excavatorVin,
courseAngle: data.courseAngle,
courseAngles: 0,
id: data.id,
type: data.type,
areaId: data.areaId,
radius: data.radius,
loadPositionModel: data.loadPositionModel,
}).addTo(tatget);
shapes.bindTooltip(tips);
if (flag == 1) {
shapes.transform.enable({ rotation: true, scaling: false });
// 箭头
var topleft = L.latLng(coordinates[1]),
topright = L.latLng(coordinates[2]),
bottomleft = L.latLng(coordinates[0]);
var str = L.imageOverlay.rotated(this.jts, topleft, topright, bottomleft, {
opacity: 1,
interactive: true,
excavatorVin: data.excavatorVin,
id: data.id,
type: data.type,
areaId: data.areaId,
radius: data.radius,
loadPositionModel: data.loadPositionModel,
}).addTo(tatget);
this.imageOverlay.push(str);
}
shapes.on('drag transformed', this.drag); // 拖动中 操作结束
shapes.on('rotate', this.transform); // 旋转中
},
增加拖动,旋转事件
// 拖动中 操作结束
drag(e) {
e.target.options.courseAngles = 0;
this.imageOverlay.forEach((item, index) => {
if (item.options.id == e.target.options.id) {
var updatedTopLeft = e.target.getLatLngs()[0][1],
updatedTopRight = e.target.getLatLngs()[0][2],
updatedBottomLeft = e.target.getLatLngs()[0][0];
item.reposition(updatedTopLeft, updatedTopRight, updatedBottomLeft);
}
});
},
// 旋转中
transform(e) {
var datas = e.target.getLatLngs()[0];
var rotationAngle = e.rotation; // 旋转角度
var dataAll = this.loadPositionLayerGroup._layers;
let center = '';
var str = [];
e.target.options.courseAngles = e.target.options.courseAngles + rotationAngle;
for (var i in dataAll) {
if (dataAll[i] && dataAll[i].transform && dataAll[i].options.id == e.target.options.id) {
center = dataAll[i].getCenter() // [lat,lng]
}
}
datas.forEach((item, index) => {
str.push(Map.rotatePoint({ x: item.lng, y: item.lat }, { x: center.lng, y: center.lat }, e.target.options.courseAngles));
});
this.imageOverlay.forEach((item, index) => {
if (item.options.id == e.target.options.id) {
var updatedTopLeft = L.latLng(0, 0),
updatedTopRight = L.latLng(0, 0),
updatedBottomLeft = L.latLng(0, 0);
item.reposition(updatedTopLeft, updatedTopRight, updatedBottomLeft);
}
});
},
点击调整装载位按钮
var dataAll = this.$parent.$refs.eqMap.loadPositionLayerGroup._layers;
for (var i in dataAll) {
if (dataAll[i].options.excavatorVin == this.realtimeObjs.vin) {
this.$parent.$refs.eqMap.loadPositionLayerGroup.removeLayer(dataAll[i]);
}
}
this.$parent.$refs.eqMap.loadAreaData.forEach((item, index) => {
if (item.excavatorVin == this.realtimeObjs.vin) {
this.$parent.$refs.eqMap.renderLoadArea(
{
areaData: item,
id: item.id
}, 1
);
}
});
调整完成保存
var dataAll = this.$parent.$refs.eqMap.loadPositionLayerGroup._layers;
var flag = 0;
for (var i in dataAll) {
if (dataAll[i].options.excavatorVin == this.realtimeObjs.vin) {
dataAll[i].transform ? this.$parent.$refs.eqMap.handleCenter(dataAll[i]) : '';
if (!dataAll[i].options.radius) {
flag = 1;
}
}
}
this.$parent.$refs.eqMap.updateLoadPosition();
// 坐标格式化
handleCenter(val) {
var center = Map.getCenterLonLat(val._latlngs[0][0].lng, val._latlngs[0][0].lat, val._latlngs[0][3].lng, val._latlngs[0][3].lat); // 两点之间中心点
let bounds = val._latlngs[0];
let rotate = Map.calcAngle(bounds[0], bounds[1], this.eqMap); // 角度
var centerPoint = Map.getLonAndLat(center[0], center[1], rotate, val.options.radius); // 后轴中心点
let coordinates = []; // 点位
bounds.map((item) => {
let str = item.lng + ',' + item.lat
coordinates.push(str)
});
coordinates = coordinates.join('#');
this.loadDatas.push({
id: val.options.id,
mapId: this.mapId,
coordinate: coordinates,
courseAngle: rotate,
centerPoint: centerPoint.lng + ',' + centerPoint.lat,
type: val.options.type,
areaId: val.options.areaId,
excavatorVin: val.options.excavatorVin
});
},
点击取消调整装载位
// 取消调整装载位
handleCloseWaji() {
var dataAll = this.$parent.$refs.eqMap.loadPositionLayerGroup._layers;
for (var i in dataAll) {
if (dataAll[i].options.excavatorVin == this.realtimeObjs.vin) {
dataAll[i].options.transform ? dataAll[i].transform.disable() : '';
dataAll[i].options.transform ? dataAll[i].dragging.disable() : '';
this.$parent.$refs.eqMap.loadPositionLayerGroup.removeLayer(dataAll[i]);
}
}
this.$parent.$refs.eqMap.getLoadAreaDtoList();
this.dragFlag = false;
},