leaflet地图轨迹回放,实时改变角度与速度

文中提到的 “标识” 名词,代表使用L.Marker 方法创建出来的点位

项目使用的leaflet地图,最近有一个需求,在地图上画出多条轨迹,然后点击一个总控制按钮,轨迹开始根据自己的时间进行挨个回放,回放过程中速度也会实时变化。
实现轨迹回放无疑就是marker标识在轨迹上面再跑一圈,也就是marker的移动,我进行搜阅,找到了两种方式:

1.可一个点一个点的来,也可一整个轨迹:转场
2.直接一整条轨迹:转场
这两种方式实现的方法各有不同,哪一种合适可以自己进行选择。(记得给大佬点赞,确实不错)

我用的第一种,但是跟我的需求还有些不同,因此我稍微进行了修改。第一种的用法为:

let marker = L.Marker.movingMarker([坐标,最少两个点], [动画时间(可为数组)], { 你自己的属性}).addTo(map);
//实际例子
let marker = L.Marker.movingMarker([[0,0],[1,1]], 1000, { 你自己的属性}).addTo(map);
marker.start();
//这样就实现了marker运动,
//若想根据速度实时运动,就在动画时间数组里面多给几个值,让他的长度和前面点的数组的长度相同,代表每个点之间的速度。如:
let marker = L.Marker.movingMarker([坐标,最少两个点], [动画时间(数组长度跟坐标长度一样)], { className:'marker' }).addTo(map);
//实际例子
let marker = L.Marker.movingMarker([[0,0],[1,1]], [1000,500], { 你自己的属性}).addTo(map);

若是再回放过程中又多了几个点,可以使用文件(MovingMarker.js)中addLatLng方法:

marker.addLatLng(坐标,时间);
//一次添加一个,若想添加数组,可以自己修改文件

如是想改变已经添加进去的点的速度,如倍速播放,可以在文件(MovingMarker.js)中添加两个方法

//getSpeed、setSpeed方法在MovingMarker.js文件中添加
//获取速度
getSpeed(){
	return this._durations 
},
//整体设置速度
setSpeed(_durations){
	this._durations = _durations;
}
//在自己文件中使用
//使用方法为:
let speed = marker.getSpeed();
marker.setSpeed(speed/10);//以10倍速进行回放

我的项目还有改变标识方向的需求,因此我又加了这个文件:
详情见:转场

(function() {
    // save these original methods before they are overwritten
    var proto_initIcon = L.Marker.prototype._initIcon;
    var proto_setPos = L.Marker.prototype._setPos;

    var oldIE = (L.DomUtil.TRANSFORM === 'msTransform');

    L.Marker.addInitHook(function () {
        var iconOptions = this.options.icon && this.options.icon.options;
        var iconAnchor = iconOptions && this.options.icon.options.iconAnchor;
        if (iconAnchor) {
            iconAnchor = (iconAnchor[0] + 'px ' + iconAnchor[1] + 'px');
        }
        this.options.rotationOrigin = this.options.rotationOrigin || iconAnchor || 'center center' ;//设置旋转中心
        this.options.rotationAngle = this.options.rotationAngle || 0;

        // Ensure marker keeps rotated during dragging
        this.on('drag', function(e) { e.target._applyRotation(); });
    });

    L.Marker.include({
        _initIcon: function() {
            proto_initIcon.call(this);
        },

        _setPos: function (pos) {
            proto_setPos.call(this, pos);
            this._applyRotation();
        },

        _applyRotation: function () {
            if(this.options.rotationAngle) {
                this._icon.style[L.DomUtil.TRANSFORM+'Origin'] = this.options.rotationOrigin;

                if(oldIE) {
                    // for IE 9, use the 2D rotation
                    this._icon.style[L.DomUtil.TRANSFORM] = 'rotate(' + this.options.rotationAngle + 'deg)';
                } else {
                    // for modern browsers, prefer the 3D accelerated version
                    this._icon.style[L.DomUtil.TRANSFORM] += ' rotateZ(' + this.options.rotationAngle + 'deg)';
                }
            }
        },
        //设置旋转角度
        setRotationAngle: function (px1, py1, px2, py2) {
            x = px2 - px1;
            y = py2 - py1;
            hypotenuse = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
            //斜边长度 
            cos = x / hypotenuse;
            radian = Math.acos(cos);
            //求出弧度 
            angle = 180 / (Math.PI / radian);
            //用弧度算出角度 
            if (y < 0) {
                angle = -angle;
            } else if ((y == 0) && (x < 0)) {
                angle = 180;
            }
            this.options.rotationAngle = angle;
            this.update();
            return this;
        },

        setRotationOrigin: function(origin) {
            this.options.rotationOrigin = origin;
            this.update();
            return this;
        }
    });
})();

此文件给L.Marker添加了setRotationAngle方法,可通过 “实例.setRotationAngle(px1,py1,px2,py2)” 进行修改标识的角度。
也可以在初始化标识的时候,加上一个rotationOrigin属性,让他在初次渲染的时候就有一个方向。

// 初次渲染时就有方向举例:
let marker = L.Marker.movingMarker(坐标, {rotationOrigin:'center center'}).addTo(map);//以图标中心点做旋转

接着上方的这个例子来说,初始化并渲染完成后,若想在轨迹回放的时候实时改变方向 (拐弯或者斜着走的时候,头部始终指向前方 ),需要在文件(MovingMarker.js)中的 _animate 方法中进行修改角度操作。阅读文件(MovingMarker.js)可发现 _animate 方法是标识移动所调用的方法。我们只需在他给标识设置下一个点坐标的时候,改变一下标识的角度即可实现我们的需求。
下面贴出文件(MovingMarker.js)中 _animate 方法,并添加下面第21行代码

_animate: function(timestamp, noRequestAnim) {
    this._animRequested = false;

    // find the next line and compute the new elapsedTime
    var elapsedTime = this._updateLine(timestamp);

    if (this.isEnded()) {
        // no need to animate
        return;
    }

    if (elapsedTime != null) {
         // compute the position
        var p = L.interpolatePosition(this._currentLine[0],
            this._currentLine[1],
            this._currentDuration,
            elapsedTime);
        //给标识设置下一个点坐标
        this.setLatLng(p);
        //为标识设置下次运动时的角度
        this.setRotationAngle(this._currentLine[0].lat,this._currentLine[0].lng,this._currentLine[1].lat,this._currentLine[1].lng)
    }

    if (! noRequestAnim) {
        this._animId = L.Util.requestAnimFrame(this._animate, this, false);
        this._animRequested = true;
    }
}

这样需求就可以实现了。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值