-
Notifications
You must be signed in to change notification settings - Fork 5
/
AnimatedLine.js
executable file
·124 lines (105 loc) · 3.11 KB
/
AnimatedLine.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
L.AnimatedLine = L.Polyline.extend({
options: {
// meters
distance: 200,
// ms
interval: 250,
// animate on add?
autoStart: true,
// callback onend
onEnd: function(){},
clickable: true,
maxDuration: 0
},
initialize: function (latlngs, options) {
this._totalDistance = 0;
// Chunk up the lines into options.distance bits
this._coords = this._chunk(latlngs);
this.options.distance = 100;
this.options.interval = 50;
this.finished = false;
L.Polyline.prototype.initialize.call(this, latlngs, options);
if ( this.options.maxDuration
&& this.options.interval * this._totalDistance/this.options.distance > this.options.maxDuration )
this.options.interval = Math.max( 1, this.options.maxDuration / (this._totalDistance/this.options.distance) );
},
// Breaks the line up into tiny chunks (see options) ONLY if CSS3 animations
// are not supported.
_chunk: function(latlngs) {
var i,
len = latlngs.length,
chunkedLatLngs = [],
totalDist = 0;
for (i=1;i<len;i++) {
var cur = latlngs[i-1],
next = latlngs[i],
dist = cur.distanceTo(next),
factor = this.options.distance / dist,
dLat = factor * (next.lat - cur.lat),
dLng = factor * (next.lng - cur.lng);
this._totalDistance += dist;
if (dist > this.options.distance) {
while (dist > this.options.distance) {
cur = new L.LatLng(cur.lat + dLat, cur.lng + dLng);
dist = cur.distanceTo(next);
chunkedLatLngs.push(cur);
}
} else {
chunkedLatLngs.push(cur);
}
}
return chunkedLatLngs;
},
onAdd: function (map) {
L.Polyline.prototype.onAdd.call(this, map);
// Start animating when added to the map
if (this.options.autoStart) {
this.start();
}
},
animate: function() {
var self = this,
len = this._coords.length,
speed = this.options.interval;
// Normalize the transition speed from vertex to vertex
if (this._i < len) {
speed = this._coords[this._i-1].distanceTo(this._coords[this._i]) / this.options.distance * this.options.interval;
}
// Move to the next vertex
this.setLatLngs(this._coords.slice(0,this._i+1));
this._i++;
// Queue up the animation ot the next next vertex
this._tid = setTimeout(function(){
if (self._i === len) {
self.finished = true;
self.options.onEnd.apply(self, Array.prototype.slice.call(arguments));
} else {
self.animate();
}
}, speed);
},
// Start the animation
start: function() {
if (!this._i) {
this._i = 1;
}
this.animate();
},
// Stop the animation in place
stop: function() {
if (this._tid) {
clearTimeout(this._tid);
}
},
finish: function() {
if (this._tid) {
clearTimeout(this._tid);
}
this.finished = true;
this.setLatLngs(this._coords);
this.options.onEnd.apply(this, Array.prototype.slice.call(arguments));
}
});
L.animatedLine = function (latlngs, options) {
return new L.AnimatedLine(latlngs, options);
};