leaflet 绘制区域支持旋转拖拽功能

实现成果:

->->->

插件

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;
        },

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Leaflet绘制航迹,您可以使用Polyline实例。Polyline是一种形状类,用于绘制连续的线段。以下是一个简单的示例: ```javascript var polyline = L.polyline([ [51.505, -0.09], [51.5, -0.1], [51.495, -0.06] ]).addTo(map); ``` 在这个例子中,我们定义了一个具有三个坐标点的Polyline对象,并将其添加到了地图上。您可以通过添加更多的坐标点来创建更复杂的航迹。 如果您想要更多的控制,您可以使用PathOptions参数来设置线段的颜色、宽度和其他样式: ```javascript var polyline = L.polyline([ [51.505, -0.09], [51.5, -0.1], [51.495, -0.06] ], { color: 'red', weight: 3, opacity: 0.5 }).addTo(map); ``` 在这个例子中,我们设置了线段的颜色为红色,线宽为3像素,不透明度为0.5。您可以根据需要进行调整。 另外,如果您想要在航迹上添加标记点,您可以使用Marker实例: ```javascript var marker1 = L.marker([51.505, -0.09]).addTo(map); var marker2 = L.marker([51.5, -0.1]).addTo(map); var marker3 = L.marker([51.495, -0.06]).addTo(map); var polyline = L.polyline([ [51.505, -0.09], [51.5, -0.1], [51.495, -0.06] ]).addTo(map); ``` 在这个例子中,我们创建了三个标记点,并将它们添加到地图上。然后,我们创建了一个Polyline对象,并将它添加到地图上。这将在航迹上绘制一条线段,并在每个标记点处添加一个标记。 希望这可以帮助您开始使用Leaflet绘制航迹。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值