Skip to content

Commit b87b630

Browse files
author
潘卓然ParnDeedlit
committed
【SDK】【Leaflet】【新增动态轨迹 & 时间轨迹图层】
1 parent 4161d11 commit b87b630

14 files changed

+2871
-3
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"webpack-parallel-uglify-plugin": "0.4.2"
6464
},
6565
"dependencies": {
66+
"@mapbox/leaflet-omnivore": "^0.3.4",
6667
"@mapbox/mapbox-gl-style-spec": "^13.15.0",
6768
"@mapgis/mapbox-gl": "^1.9.0",
6869
"axios": "^0.18.0",

src/config/opensource/leaflet_index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,15 @@ import {
651651
StreamLayer,
652652
HeaterLayer,
653653
ClusterLayer,
654-
MarkerClusterLayer
654+
MarkerClusterLayer,
655+
AnimatedMarkerLayer,
656+
TimeDimension,
657+
TimeDimensionControl,
658+
TimeDimensionLayer,
659+
TimeDimensionLayerGeoJson,
660+
TimeDimensionLayerWMS,
661+
TimeDimensionPlayer,
662+
TimeDimensionUtil
655663
} from '../../leaflet/overlay/index.js';
656664

657665
export {
@@ -660,5 +668,13 @@ export {
660668
StreamLayer,
661669
HeaterLayer,
662670
ClusterLayer,
663-
MarkerClusterLayer
671+
MarkerClusterLayer,
672+
AnimatedMarkerLayer,
673+
TimeDimension,
674+
TimeDimensionControl,
675+
TimeDimensionLayer,
676+
TimeDimensionLayerGeoJson,
677+
TimeDimensionLayerWMS,
678+
TimeDimensionPlayer,
679+
TimeDimensionUtil
664680
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import L from "leaflet";
2+
3+
/**
4+
* @author 基础平台/创新中心 潘卓然 ParnDeedlit
5+
* @class L.zondy.AnimatedMarkerLayer
6+
* @classdesc 基于leaflet的Layer对象进行的拓展
7+
* @extends {L.Marker}
8+
* @param {string} latlngs - 轨迹点
9+
*/
10+
export var AnimatedMarkerLayer = L.Marker.extend({
11+
options: {
12+
// meters
13+
distance: 200,
14+
// ms
15+
interval: 1000,
16+
// animate on add?
17+
autoStart: true,
18+
// callback onend
19+
onEnd: function () { },
20+
clickable: false
21+
},
22+
23+
initialize: function (latlngs, options) {
24+
this.setLine(latlngs);
25+
L.Marker.prototype.initialize.call(this, latlngs[0], options);
26+
},
27+
28+
// Breaks the line up into tiny chunks (see options) ONLY if CSS3 animations
29+
// are not supported.
30+
_chunk: function (latlngs) {
31+
var i,
32+
len = latlngs.length,
33+
chunkedLatLngs = [];
34+
35+
for (i = 1; i < len; i++) {
36+
var cur = latlngs[i - 1],
37+
next = latlngs[i],
38+
dist = cur.distanceTo(next),
39+
factor = this.options.distance / dist,
40+
dLat = factor * (next.lat - cur.lat),
41+
dLng = factor * (next.lng - cur.lng);
42+
43+
if (dist > this.options.distance) {
44+
while (dist > this.options.distance) {
45+
cur = new L.LatLng(cur.lat + dLat, cur.lng + dLng);
46+
dist = cur.distanceTo(next);
47+
chunkedLatLngs.push(cur);
48+
}
49+
} else {
50+
chunkedLatLngs.push(cur);
51+
}
52+
}
53+
chunkedLatLngs.push(latlngs[len - 1]);
54+
55+
return chunkedLatLngs;
56+
},
57+
58+
onAdd: function (map) {
59+
L.Marker.prototype.onAdd.call(this, map);
60+
61+
// Start animating when added to the map
62+
if (this.options.autoStart) {
63+
this.start();
64+
}
65+
},
66+
67+
animate: function () {
68+
var self = this,
69+
len = this._latlngs.length,
70+
speed = this.options.interval;
71+
72+
// Normalize the transition speed from vertex to vertex
73+
if (this._i < len && this._i > 0) {
74+
speed = this._latlngs[this._i - 1].distanceTo(this._latlngs[this._i]) / this.options.distance * this.options.interval;
75+
}
76+
77+
// Only if CSS3 transitions are supported
78+
if (L.DomUtil.TRANSITION) {
79+
if (this._icon) { this._icon.style[L.DomUtil.TRANSITION] = ('all ' + speed + 'ms linear'); }
80+
if (this._shadow) { this._shadow.style[L.DomUtil.TRANSITION] = 'all ' + speed + 'ms linear'; }
81+
}
82+
83+
// Move to the next vertex
84+
this.setLatLng(this._latlngs[this._i]);
85+
this._i++;
86+
87+
// Queue up the animation to the next next vertex
88+
this._tid = setTimeout(function () {
89+
if (self._i === len) {
90+
self.options.onEnd.apply(self, Array.prototype.slice.call(arguments));
91+
} else {
92+
self.animate();
93+
}
94+
}, speed);
95+
},
96+
97+
// Start the animation
98+
start: function () {
99+
this.animate();
100+
},
101+
102+
// Stop the animation in place
103+
stop: function () {
104+
if (this._tid) {
105+
clearTimeout(this._tid);
106+
}
107+
},
108+
109+
setLine: function (latlngs) {
110+
if (L.DomUtil.TRANSITION) {
111+
// No need to to check up the line if we can animate using CSS3
112+
this._latlngs = latlngs;
113+
} else {
114+
// Chunk up the lines into options.distance bits
115+
this._latlngs = this._chunk(latlngs);
116+
this.options.distance = 10;
117+
this.options.interval = 30;
118+
}
119+
this._i = 0;
120+
}
121+
});
122+
123+
export var animatedMarkerLayer = function(latlngs, options) {
124+
return new AnimatedMarkerLayer(latlngs, options);
125+
};
126+
127+
L.zondy.AnimatedMarkerLayer = animatedMarkerLayer;

src/leaflet/overlay/index.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,34 @@ import {
2222
MarkerClusterLayer
2323
} from './view/MarkerClusterLayer';
2424

25+
import {
26+
AnimatedMarkerLayer
27+
} from './AnimatedMarkerLayer';
28+
29+
import {
30+
TimeDimension,
31+
TimeDimensionControl,
32+
TimeDimensionLayer,
33+
TimeDimensionLayerGeoJson,
34+
TimeDimensionLayerWMS,
35+
TimeDimensionPlayer,
36+
TimeDimensionUtil
37+
} from './timedimension'
38+
2539
export {
2640
EchartsLayer,
2741
MapvLayer,
2842
StreamLayer,
2943
HeaterLayer,
3044
ClusterLayer,
31-
MarkerClusterLayer
45+
MarkerClusterLayer,
46+
AnimatedMarkerLayer,
47+
48+
TimeDimension,
49+
TimeDimensionControl,
50+
TimeDimensionLayer,
51+
TimeDimensionLayerGeoJson,
52+
TimeDimensionLayerWMS,
53+
TimeDimensionPlayer,
54+
TimeDimensionUtil
3255
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { TimeDimension } from './leaflet.timedimension';
2+
import { TimeDimensionControl } from './leaflet.timedimension.control';
3+
import { TimeDimensionLayer } from './leaflet.timedimension.layer';
4+
import { TimeDimensionLayerGeoJson } from './leaflet.timedimension.layer.geojson';
5+
import { TimeDimensionLayerWMS } from './leaflet.timedimension.layer.wms';
6+
import { TimeDimensionPlayer } from './leaflet.timedimension.player';
7+
import { TimeDimensionUtil } from "./leaflet.timedimension.util";
8+
9+
10+
export {
11+
TimeDimension,
12+
TimeDimensionControl,
13+
TimeDimensionLayer,
14+
TimeDimensionLayerGeoJson,
15+
TimeDimensionLayerWMS,
16+
TimeDimensionPlayer,
17+
TimeDimensionUtil
18+
};
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
export var iso8601 = {
2+
Period: {}
3+
};
4+
5+
// create sub packages
6+
7+
//---- public properties
8+
9+
/**
10+
* version of the ISO8601 version
11+
*/
12+
iso8601.version = '0.2';
13+
14+
//---- public methods
15+
16+
/**
17+
* Returns an array of the duration per unit. The normalized sum of all array elements
18+
* represents the total duration.
19+
*
20+
* - array[0]: years
21+
* - array[1]: months
22+
* - array[2]: weeks
23+
* - array[3]: days
24+
* - array[4]: hours
25+
* - array[5]: minutes
26+
* - array[6]: seconds
27+
*
28+
* @param period iso8601 period string
29+
* @param distributeOverflow if 'true', the unit overflows are merge into the next higher units. Defaults to 'false'.
30+
*/
31+
iso8601.Period.parse = function (period, distributeOverflow) {
32+
return parsePeriodString(period, distributeOverflow);
33+
};
34+
35+
/**
36+
* Returns the total duration of the period in seconds.
37+
*/
38+
iso8601.Period.parseToTotalSeconds = function (period) {
39+
40+
var multiplicators = [31104000 /* year (360*24*60*60) */,
41+
2592000 /* month (30*24*60*60) */,
42+
604800 /* week (24*60*60*7) */,
43+
86400 /* day (24*60*60) */,
44+
3600 /* hour (60*60) */,
45+
60 /* minute (60) */,
46+
1 /* second (1) */];
47+
var durationPerUnit = parsePeriodString(period);
48+
var durationInSeconds = 0;
49+
50+
for (var i = 0; i < durationPerUnit.length; i++) {
51+
durationInSeconds += durationPerUnit[i] * multiplicators[i];
52+
}
53+
54+
return durationInSeconds;
55+
};
56+
57+
/**
58+
* Return boolean based on validity of period
59+
* @param period
60+
* @return {Boolean}
61+
*/
62+
iso8601.Period.isValid = function (period) {
63+
try {
64+
parsePeriodString(period);
65+
return true;
66+
} catch (e) {
67+
return false;
68+
}
69+
}
70+
71+
/**
72+
* Returns a more readable string representation of the ISO8601 period.
73+
* @param period the ISO8601 period string
74+
* @param unitName the names of the time units if there is only one (such as hour or minute).
75+
* Defaults to ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'].
76+
* @param unitNamePlural thenames of the time units if there are several (such as hours or minutes).
77+
* Defaults to ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'].
78+
* @param distributeOverflow if 'true', the unit overflows are merge into the next higher units. Defaults to 'false'.
79+
*/
80+
iso8601.Period.parseToString = function (period, unitNames, unitNamesPlural, distributeOverflow) {
81+
82+
var result = ['', '', '', '', '', '', ''];
83+
var durationPerUnit = parsePeriodString(period, distributeOverflow);
84+
85+
// input validation (use english as default)
86+
if (!unitNames) unitNames = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'];
87+
if (!unitNamesPlural) unitNamesPlural = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'];
88+
89+
// assemble string per unit
90+
for (var i = 0; i < durationPerUnit.length; i++) {
91+
if (durationPerUnit[i] > 0) {
92+
if (durationPerUnit[i] == 1) result[i] = durationPerUnit[i] + " " + unitNames[i];
93+
else result[i] = durationPerUnit[i] + " " + unitNamesPlural[i];
94+
}
95+
}
96+
97+
// trim because of space at very end and because of join(" ")
98+
// replace double spaces because of join(" ") and empty strings
99+
// Its actually possible to get more than 2 spaces in a row,
100+
// so lets get 2+ spaces and remove them
101+
return result.join(' ').trim().replace(/[ ]{2,}/g, ' ');
102+
};
103+
104+
//---- private methods
105+
106+
/**
107+
* Parses a ISO8601 period string.
108+
* @param period iso8601 period string
109+
* @param _distributeOverflow if 'true', the unit overflows are merge into the next higher units.
110+
*/
111+
function parsePeriodString(period, _distributeOverflow) {
112+
113+
// regex splits as follows
114+
// grp0 omitted as it is equal to the sample
115+
//
116+
// | sample | grp1 | grp2 | grp3 | grp4 | grp5 | grp6 | grp7 | grp8 | grp9 |
117+
// --------------------------------------------------------------------------------------------
118+
// | P1Y2M3W | 1Y2M3W | 1Y | 2M | 3W | 4D | T12H30M17S | 12H | 30M | 17S |
119+
// | P3Y6M4DT12H30M17S | 3Y6M4D | 3Y | 6M | | 4D | T12H30M17S | 12H | 30M | 17S |
120+
// | P1M | 1M | | 1M | | | | | | |
121+
// | PT1M | 3Y6M4D | | | | | T1M | | 1M | |
122+
// --------------------------------------------------------------------------------------------
123+
124+
var distributeOverflow = (_distributeOverflow) ? _distributeOverflow : false;
125+
var valueIndexes = [2, 3, 4, 5, 7, 8, 9];
126+
var duration = [0, 0, 0, 0, 0, 0, 0];
127+
var overflowLimits = [0, 12, 4, 7, 24, 60, 60];
128+
var struct;
129+
130+
// upcase the string just in case people don't follow the letter of the law
131+
period = period.toUpperCase();
132+
133+
// input validation
134+
if (!period) return duration;
135+
else if (typeof period !== "string") throw new Error("Invalid iso8601 period string '" + period + "'");
136+
137+
// parse the string
138+
if (struct = /^P((\d+Y)?(\d+M)?(\d+W)?(\d+D)?)?(T(\d+H)?(\d+M)?(\d+S)?)?$/.exec(period)) {
139+
140+
// remove letters, replace by 0 if not defined
141+
for (var i = 0; i < valueIndexes.length; i++) {
142+
var structIndex = valueIndexes[i];
143+
duration[i] = struct[structIndex] ? +struct[structIndex].replace(/[A-Za-z]+/g, '') : 0;
144+
}
145+
}
146+
else {
147+
throw new Error("String '" + period + "' is not a valid ISO8601 period.");
148+
}
149+
150+
if (distributeOverflow) {
151+
// note: stop at 1 to ignore overflow of years
152+
for (var i = duration.length - 1; i > 0; i--) {
153+
if (duration[i] >= overflowLimits[i]) {
154+
duration[i - 1] = duration[i - 1] + Math.floor(duration[i] / overflowLimits[i]);
155+
duration[i] = duration[i] % overflowLimits[i];
156+
}
157+
}
158+
}
159+
160+
return duration;
161+
};

0 commit comments

Comments
 (0)