vue3中高德地图JSAPI 2.0加载gltf模型的轨迹回放

预览

大概思路是:

  • 获取高德地图的公交路线坐标数组
  • 加载gltf模型
  • 根据公交线路的坐标绘制轨迹
  • 监听事件moving修改gltf模型的位置

获取公交线路坐标的代码如下(轨迹回放

var transOptions = {
    map: map,
    city: "武汉市",
    panel: "panel",
    policy: AMap.TransferPolicy.LEAST_TIME, //乘车策略
};
var pointArr = []; // 存储公交经过的坐标,是一个二维数组

var transfer = new AMap.Transfer(transOptions);

transfer.search(
    [
        { keyword: "园博园", city: "武汉" },
        { keyword: "金银潭地铁站", city: "武汉" },
    ],
    function (status, result) {
        if (status === "complete") {
            for (var i = 0; i < result.plans[0].path.length; i++) {
                pointArr.push([result.plans[0].path[i].lng, result.plans[0].path[i].lat]);
            }
            resolve(pointArr); // 异步操作完成,将结果传递给resolve函数
        } else {
            console.log("公交路线数据查询失败,错误代码:" + result);
            reject("查询失败"); // 异步操作失败,将错误信息传递给reject函数
        }
    }
);

这里会得到公交线路的坐标,存储在pointArr数组中,内容如下

pointArr = [[114.218315, 30.62306],
        [114.218315, 30.622686],
        [114.218315, 30.622087],
        ·····]

marker移动事件的监听

// 绑定移动事件监听器
marker.on("moving", function (e) {
    var passedPath = e.passedPath, lastPosi = passedPath[passedPath.length - 1];
    passedPolyline.setPath(passedPath);
    var angle = calcAngle([passedPath[passedPath.length - 2][0], passedPath[passedPath.length - 2][1]], [lastPosi.lng, lastPosi.lat]);

    // 判断角度变化的大小是否超过阈值(2度)
    if (Math.abs(angle - previousAngle) >= 2) {
        setAngle(angle);
        previousAngle = angle;
    }
    startMove(lastPosi); // 移动gltf模型
});

完整代码

这里省略了map的创建等,只展示了关于公交车线路和模型的部分代码,其余代码需要读者自己补充

immediate_bus() {
    function initGltf() {
        var loader = new GLTFLoader();
        loader.load("bus.glb", gltf => {
            busobj = gltf.scene;
            busobj.scale.set(10, 10, 10);
            busobj.renderOrder = 999;
            setRotation({ x: 90, y: 0, z: 0 });
            setPosition(map_init_center);
            scene.add(busobj);
        });
    }
    function setRotation(rotation) {
        var x = (Math.PI / 180) * (rotation.x || 0);
        var y = (Math.PI / 180) * (rotation.y || 0);
        var z = (Math.PI / 180) * (rotation.z || 0);
        busobj.rotation.set(x, y, z);
    }
    function setPosition(lnglat) {
        // 对模型的经纬度进行转换
        var position = customCoords.lngLatsToCoords([lnglat])[0];
        busobj.position.setX(position[0]);
        busobj.position.setY(position[1]);
    }
    function setAngle(angle) {
        var x = busobj.rotation.x;
        var z = busobj.rotation.z;
        var y = (Math.PI / 180) * angle;
        busobj.rotation.set(x, y, z);
    }
    // 计算地图上两点间的角度
    function calcAngle(start, end) {
        var diff_lng = end[0] - start[0];
        var diff_lat = end[1] - start[1];
        return (360 * Math.atan2(diff_lat, diff_lng)) / (2 * Math.PI);
    }

    // 改变模型位置和角度
    var xe = -5.341658, ye = 3.738671; // 坐标偏移量,因为坐标系原因,偏移量需要自己设定,(归根到底还是该死的火星坐标系)
    function startMove(Position) {
        var centerPoint = turf.point([Position.lng + xe, Position.lat + ye]);
        var pos = turf.transformTranslate(centerPoint, 0.3, 0).geometry.coordinates;
        setPosition(pos);
    }
    function init() {
        marker = new AMap.Marker({
            map: map,
            position: lineArr[0],
            // icon: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png",
            content: "<div style='display:none'></div>",
        });

        // 绘制轨迹
        polyline = new AMap.Polyline({
            map: map,
            path: lineArr,
            showDir: true,
            strokeColor: "#28F", //线颜色
            strokeOpacity: 0.3, //线透明度
            strokeWeight: 6, //线宽
            // strokeStyle: "solid"  //线样式
        });

        // 经过的轨迹修改颜色
        passedPolyline = new AMap.Polyline({
            map: map,
            strokeColor: "#AF5", //线颜色
            strokeWeight: 6, //线宽
            strokeOpacity: 0.3, //线透明度
        });
        // 声明一个变量用于存储上一次的角度
        var previousAngle = 0;
        // 绑定移动事件监听器
        marker.on("moving", function (e) {
            var passedPath = e.passedPath,
                lastPosi = passedPath[passedPath.length - 1];
            passedPolyline.setPath(passedPath);
            var angle = calcAngle([passedPath[passedPath.length - 2][0], passedPath[passedPath.length - 2][1]], [lastPosi.lng, lastPosi.lat]);

            // 判断角度变化的大小是否超过阈值(2度)
            if (Math.abs(angle - previousAngle) >= 2) {
                setAngle(angle);
                previousAngle = angle;
            }
            startMove(lastPosi);
        });
    }
    let origin_terminus = this;
    function find_road() {
        return new Promise(function (resolve, reject) { // 因为transfer.search是异步加载的,而我们需要等待查询结束后返回坐标。
            var transOptions = {
                map: map,
                city: "武汉市",
                panel: "panel",
                policy: AMap.TransferPolicy.LEAST_TIME, //乘车策略
            };
            var pointArr = [];

            var transfer = new AMap.Transfer(transOptions);

            transfer.search(
                [
                    { keyword: origin_terminus.origin, city: "武汉" },
                    { keyword: origin_terminus.terminus, city: "武汉" },
                ],
                function (status, result) {
                    if (status === "complete") {
                        for (var i = 0; i < result.plans[0].path.length; i++) {
                            pointArr.push([result.plans[0].path[i].lng, result.plans[0].path[i].lat]);
                        }
                        resolve(pointArr); // 异步操作完成,将结果传递给resolve函数
                    } else {
                        console.log("公交路线数据查询失败,错误代码:" + result);
                        reject("查询失败"); // 异步操作失败,将错误信息传递给reject函数
                    }
                }
            );
        })
            .then(function (pointArr) {
                if (pointArr.length === 0) { // 查询不到数据,返回默认坐标
                    return [
                        [114.218315, 30.62306],
                        [114.218315, 30.622686],
                    ];
                } else {
                    return pointArr;
                }
            })
            .catch(function (error) {
                console.log(error);
            });
    }

    async function init_bus() {  // 确保获取到公交线路的坐标后,在执行其他函数
        lineArr = await find_road();
        initGltf();
        init();
        map.add(marker);
        scene.add(busobj);
        map.add(polyline);
        map.add(passedPolyline);
        marker.moveAlong(lineArr, {
            duration: 8000,
            autoRotation: true,
        });
    }
    init_bus();
},

如有不明白的地方可以留言,博主闲暇时会给与回答。

作者:WuQiling
文章链接:https://www.wqlblog.cn/vue中高德地图jsapi-2-0加载gltf模型的轨迹回放/
文章采用 CC BY-NC-SA 4.0 协议进行许可,转载请遵循协议
暂无评论

发送评论 编辑评论


				
默认
贴吧
上一篇
下一篇