/* * @Author: hisense.wuhongjian * @Date: 2022-03-22 11:13:25 * @LastEditors: hisense.wuhongjian * @LastEditTime: 2022-03-22 11:13:25 * @Description: 告诉大家这是什么 */ 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: false, 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; 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() { if (this._animRequested) { L.Util.cancelAnimFrame(this._animId); this._animRequested = false; } }, _updatePosition: function() { var elapsedTime = Date.now() - this._startTime; this._animate(this._startTimeStamp + elapsedTime, true); }, _loadLine: function(index) { this._currentIndex = index; this._currentDuration = this._durations[index]; this._currentLine = this._latlngs.slice(index, index + 2); }, /** * Load the line where the marker is * @param {Number} timestamp * @return {Number} elapsed time on the current line or null if * we reached the end or marker is at a station */ _updateLine: function(timestamp) { // time elapsed since the last latlng var elapsedTime = timestamp - this._startTimeStamp; // not enough time to update the line if (elapsedTime <= this._currentDuration) { return elapsedTime; } var lineIndex = this._currentIndex; var lineDuration = this._currentDuration; var stationDuration; while (elapsedTime > lineDuration) { // substract time of the current line elapsedTime -= lineDuration; stationDuration = this._stations[lineIndex + 1]; // test if there is a station at the end of the line if (stationDuration !== undefined) { if (elapsedTime < stationDuration) { this.setLatLng(this._latlngs[lineIndex + 1]); return null; } elapsedTime -= stationDuration; } lineIndex++; // test if we have reached the end of the polyline if (lineIndex >= this._latlngs.length - 1) { if (this.options.loop) { lineIndex = 0; this.fire('loop', {elapsedTime: elapsedTime}); } else { // place the marker at the end, else it would be at // the last position this.setLatLng(this._latlngs[this._latlngs.length - 1]); this.stop(elapsedTime); return null; } } lineDuration = this._durations[lineIndex]; } this._loadLine(lineIndex); this._startTimeStamp = timestamp - elapsedTime; this._startTime = Date.now() - elapsedTime; return elapsedTime; }, _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); } if (! noRequestAnim) { this._animId = L.Util.requestAnimFrame(this._animate, this, false); this._animRequested = true; } } }); L.Marker.movingMarker = function (latlngs, duration, options) { return new L.Marker.MovingMarker(latlngs, duration, options); };