L.interpolatePosition = function (p1, p2, duration, t) { if (!p1 || !p2) { return; } 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.AngleMarker.extend({ //state constants statics: { notStartedState: 0, endedState: 1, pausedState: 2, runState: 3 }, options: { autostart: false, loop: false, }, initialize: function (latlngs, durations, options) { L.AngleMarker.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 = {}; this._gjLayer = L.layerGroup().addTo(window.map); this.circleLayer = [] this.isFollow = false }, 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.AngleMarker.prototype.onAdd.call(this, map); if (this.options.autostart && (!this.isStarted())) { this.start(); return; } if (this.isRunning()) { this._resumeAnimation(); } }, onRemove: function (map) { L.AngleMarker.prototype.onRemove.call(this, map); this._stopAnimation(); }, follow: function () { this.isFollow = true if (this.isFollow) { this._map.setZoom(10, { animate: false }) this._map.panTo(this.getLatLng(), { animate: false }) } }, stopFollow: function () { this.isFollow = false }, del: function () { this.circleLayer.forEach((e) => { this._gjLayer.removeLayer(e) }) }, _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); this.setIcon(new L.AngleIcon({ course: this.options.courses[index + 1], speed: this.options.speeds[index + 1], iconUrl: this.options.iconUrl , label: this.options.title , showTitle: this.options.showTitle , labelPosition: this.options.labelPosition })); //处理过虚拟位置不打点 if (!(index in this.options.noRealtimeGjList)) { var len = this.options.collectimes[index].length var title = '-'; if(len === 13){ title = formatDate(this.options.collectimes[index] * 1); }else if(len === 10){ title = formatDate(this.options.collectimes[index] * 1000) } var circlePoint = L.circleMarker(this._latlngs[index], { zIndexOffset: 10, title: title, radius: 3, color: 'blue' }).addTo(this._gjLayer); this.circleLayer.push(circlePoint) circlePoint.attributes = this.options.gjData[index]; circlePoint.bindPopup(this.options.markerPopup(circlePoint.attributes), { autoPan: false, closeButton: false, offset: L.point(130, 255) }); //autoPanPaddingBottomRight ,,{autoPan:false,closeButton:false,offset:L.point(120,185)} // var url = _this._jsonUrl+"?format=json&layer="+_this.options.gjLayer+"&customsQuery="+encodeURIComponent("{\"must\":[{\"term\":{\"attributes._targetID\":\""+attr.attributes._targetID+"\"}},{\"range\":{\"attributes.collectime\":{\"lte\":"+endTime+",\"gt\":"+startTime+"}}}]}")+"&sort=collectime:asc"; let _this = this; circlePoint.on('mouseover', function (ev) { if (_this.options.pupopOpenHander) { clearTimeout(_this.options.pupopOpenHander); } _this.options.pupopOpenHander = setTimeout(function () { ev.target.openPopup(); }, 500); if (_this.options.markerDrawJ) { _this.options.layerGroup.removeLayer(_this.options.markerDrawJ) } _this.options.markerDrawJ = L.marker(ev.target.getLatLng(), { icon: new L.AngleIcon({ iconSize: new L.Point(32, 32) }) }).addTo(_this.options.layerGroup); _this.options.markerDrawJ.options.icon.drawJ(); }); if (this.options.gjTimeMarker && this.options.layerGroup) { if (this.options.gjTimeMarker[index]) { this.options.gjTimeMarker[index].addTo(this.options.layerGroup); } } } //console.log(this._latlngs); //console.log(this._currentLine); //console.log(index); // console.log(this.options.courses[index+1]); }, /** * 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; if (!this._currentDuration) { this.stop(elapsedTime); return null; } // 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 // console.log(this._currentLine[0],this._currentLine[1],this._currentDuration,elapsedTime) var p = L.interpolatePosition(this._currentLine[0], this._currentLine[1], this._currentDuration, elapsedTime); if (p) { var angle = this.getAngle(this.getLatLng(), p); this.setLatLng(p); if (this.isFollow) { this._map.panTo(p) } //console.log(angle); /*if(angle != 0 ){ //this.updatePosAndIcon(this._map,p); if(this._map){ var _map = this._map; //L.DomUtil.remove(this._icon); _map.removeLayer(this); this.setLatLng(p); _map.addLayer(this); } }*/ } } 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); };