利用leaflet做一个飞机航线 可根据方向动态掉头

利用开源的leaflet结合天地图底图,做一条航线 可以在线上动态加载飞机icon,模仿飞机飞行状态
插件下载地址:https://download.csdn.net/download/weixin_42609477/11463900

先上效果图

在这里插入图片描述

首先将线画出来

function paintLine(A,B,C) 
	{
		var obj,color,weight;
		obj = color = weight = null;
		obj = A;
		color = B;
		weight = C;
		if(obj == null){
			console.log("无数据可供绘制!");
			return;
		}
		if(color == null)	color = "red";
		if(weight == null)	weight = 2;
		
		for(var i=0;i<obj.length-1;++i)
		{
			var roil = [L.latLng(obj[i][0],obj[i][1]),L.latLng(obj[i+1][0],obj[i+1][1])];
			L.polyline(roil, { color: color, weight: weight }).addTo(map);
		}
	}

引用js

(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;
        }
    });
})();

MovingMarker.js

L.interpolatePosition = function(p1, p2, duration, t) {
    var k = t/duration;
    k = (k > 0) ? k : 0;
    k = (k > 1) ? 1 : k;
    return L.latLng(p1.lat + k * (p2.lat - p1.lat),
        p1.lng + k * (p2.lng - p1.lng));
};

L.Marker.MovingMarker = L.Marker.extend({

    //state constants
    statics: {
        notStartedState: 0,
        endedState: 1,
        pausedState: 2,
        runState: 3
    },

    options: {
        autostart: true,
        loop: false,
    },

    initialize: function (latlngs, durations, options) {
        L.Marker.prototype.initialize.call(this, latlngs[0], options);

        this._latlngs = latlngs.map(function(e, index) {
            return L.latLng(e);
        });

        if (durations instanceof Array) {
            this._durations = durations;
        } else {
            this._durations = this._createDurations(this._latlngs, durations);
        }

        this._currentDuration = 0;
        this._currentIndex = 0;

        this._state = L.Marker.MovingMarker.notStartedState;
        this._startTime = 0;
        this._startTimeStamp = 0;  // timestamp given by requestAnimFrame
        this._pauseStartTime = 0;
        this._animId = 0;
        this._animRequested = false;
        this._currentLine = [];
        this._stations = {};
    },

    isRunning: function() {
        return this._state === L.Marker.MovingMarker.runState;
    },

    isEnded: function() {
        return this._state === L.Marker.MovingMarker.endedState;
    },

    isStarted: function() {
        return this._state !== L.Marker.MovingMarker.notStartedState;
    },

    isPaused: function() {
        return this._state === L.Marker.MovingMarker.pausedState;
    },

    start: function() {
        if (this.isRunning()) {
            return;
        }

        if (this.isPaused()) {
            this.resume();
        } else {
            this._loadLine(0);
            this._startAnimation();
            this.fire('start');
        }
    },

    resume: function() {
        if (! this.isPaused()) {
            return;
        }
        // update the current line
        this._currentLine[0] = this.getLatLng();
        this._currentDuration -= (this._pauseStartTime - this._startTime);
        this._startAnimation();
    },

    pause: function() {
        if (! this.isRunning()) {
            return;
        }

        this._pauseStartTime = Date.now();
        this._state = L.Marker.MovingMarker.pausedState;
        this._stopAnimation();
        this._updatePosition();
    },

    stop: function(elapsedTime) {
        if (this.isEnded()) {
            return;
        }

        this._stopAnimation();

        if (typeof(elapsedTime) === 'undefined') {
            // user call
            elapsedTime = 0;
            this._updatePosition();
        }

        this._state = L.Marker.MovingMarker.endedState;
        this.fire('end', {elapsedTime: elapsedTime});
    },

    addLatLng: function(latlng, duration) {
        this._latlngs.push(L.latLng(latlng));
        this._durations.push(duration);
    },

    moveTo: function(latlng, duration) {
        this._stopAnimation();
        this._latlngs = [this.getLatLng(), L.latLng(latlng)];
        this._durations = [duration];
        this._state = L.Marker.MovingMarker.notStartedState;
        this.start();
        this.options.loop = false;
    },
	
    addStation: function(pointIndex, duration) {
        if (pointIndex > this._latlngs.length - 2 || pointIndex < 1) {
            return;
        }
        this._stations[pointIndex] = duration;
    },

    onAdd: function (map) {
        L.Marker.prototype.onAdd.call(this, map);

        if (this.options.autostart && (! this.isStarted())) {
            this.start();
            return;
        }

        if (this.isRunning()) {
            this._resumeAnimation();
        }
    },

    onRemove: function(map) {
        L.Marker.prototype.onRemove.call(this, map);
        this._stopAnimation();
    },

    _createDurations: function (latlngs, duration) {
        var lastIndex = latlngs.length - 1;
        var distances = [];
        var totalDistance = 0;
        var distance = 0;

        // compute array of distances between points
        for (var i = 0; i < lastIndex; i++) {
            distance = latlngs[i + 1].distanceTo(latlngs[i]);
            distances.push(distance);
            totalDistance += distance;
        }

        var ratioDuration = duration / totalDistance;

        var durations = [];
        for (i = 0; i < distances.length; i++) {
            durations.push(distances[i] * ratioDuration);
        }

        return durations;
    },

    _startAnimation: function() {
        this._state = L.Marker.MovingMarker.runState;
		//requestAnimFrame:CSS方法动画循环
        this._animId = L.Util.requestAnimFrame(function(timestamp) {
            this._startTime = Date.now();
            this._startTimeStamp = timestamp;
            this._animate(timestamp);
        }, this, true);
        this._animRequested = true;
    },

    _resumeAnimation: function() {
        if (! this._animRequested) {
            this._animRequested = true;
            this._animId = L.Util.requestAnimFrame(function(timestamp) {
                this._animate(timestamp);
            }, this, true);
        }
    },

    _stopAnimation: function() {

添加动画

/*添加动画*/
		function addAnimation(A,marker,picture)
		{			
			marker = L.Marker.movingMarker(A,2000, {autostart: true});
            var moveicon = L.icon({
                iconUrl: picture,
				iconSize: [30, 30]
			});
			marker.options.icon = moveicon;
			marker.options.rotationOrigin = "center center";//以图标中心点做旋转
			map.addLayer(marker );
		}
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
1. 首先,需要导入leaflet库和地图数据。 ``` <!--leaflet库--> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-4eMZ4nG8EeB9Mn+rA3vz3qhlW1iQK1xQZQ2oTgNtWdR9jpJb2ay7QKjPfRg7VpJxGS44C7Vl3jK3+7VXfRH0iw==" crossorigin="" /> <script src="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-1zY5m5n5cLGn6PZU6wzv+1gj2n9XkN2y2QjD6PnozF+Jp6xhZV7q3Ki3+ZV1lXjK0sVlLJq3Wt1OJjxOc2Q64A==" crossorigin=""></script> <!--地图数据--> <script src="https://cdn.jsdelivr.net/npm/leaflet-gpx/gpx.js"></script> ``` 2. 创建一个地图容器。 ``` <div id="map" style="height: 500px;"></div> ``` ``` var map = L.map('map').setView([51.505, -0.09], 13); // 创建一个地图容器,并设置中心点和缩放级别 ``` 3. 添加一个线。 ``` var polyline = L.polyline([ [51.505, -0.09], [51.51, -0.1], [51.51, -0.12] ], {color: 'red'}).addTo(map); ``` 完整代码如下: ``` <!DOCTYPE html> <html> <head> <title>添加线</title> <meta charset="utf-8" /> <!--leaflet库--> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-4eMZ4nG8EeB9Mn+rA3vz3qhlW1iQK1xQZQ2oTgNtWdR9jpJb2ay7QKjPfRg7VpJxGS44C7Vl3jK3+7VXfRH0iw==" crossorigin="" /> <script src="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-1zY5m5n5cLGn6PZU6wzv+1gj2n9XkN2y2QjD6PnozF+Jp6xhZV7q3Ki3+ZV1lXjK0sVlLJq3Wt1OJjxOc2Q64A==" crossorigin=""></script> <!--地图数据--> <script src="https://cdn.jsdelivr.net/npm/leaflet-gpx/gpx.js"></script> </head> <body> <div id="map" style="height: 500px;"></div> <script> var map = L.map('map').setView([51.505, -0.09], 13); // 创建一个地图容器,并设置中心点和缩放级别 var polyline = L.polyline([ [51.505, -0.09], [51.51, -0.1], [51.51, -0.12] ], { color: 'red' }).addTo(map); // 添加一条线 </script> </body> </html> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gis_KG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值