Skip to content

Commit

Permalink
Unified animation to use proper map projection.
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor-Vladyka committed Apr 14, 2020
1 parent cf819f5 commit 1bf9cf8
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 32 deletions.
6 changes: 3 additions & 3 deletions dist/leaflet.motion.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/leaflet.motion.min.js

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,19 @@
}, {
removeOnEnd: true,
icon: L.divIcon({html: "<i class='fa fa-car fa-2x' aria-hidden='true'></i>", iconSize: L.point(27.5, 24)})
}).motionDuration(5000),
}).motionDuration(7000),
L.motion.seq([L.motion.polyline(planeRoute1, {
color:"indigo"
}, null, {
removeOnEnd: true,
icon: L.divIcon({html: "<i class='fa fa-plane fa-2x' aria-hidden='true' motion-base='-45'></i>", iconSize: L.point(19, 24)})
}).motionDuration(0),
icon: L.divIcon({html: "<i class='fa fa-plane fa-2x' aria-hidden='true' motion-base='-43'></i>", iconSize: L.point(19, 24)})
}).motionDuration(5000),
L.motion.polyline(planeRoute2, {
color:"khaki"
}, null, {
removeOnEnd: true,
icon: L.divIcon({html: "<i class='fa fa-plane fa-2x' aria-hidden='true' motion-base='-45'></i>", iconSize: L.point(19, 24)})
}).motionDuration(3000)
icon: L.divIcon({html: "<i class='fa fa-plane fa-2x' aria-hidden='true' motion-base='-48'></i>", iconSize: L.point(19, 24)})
}).motionDuration(7000)
])
]).addTo(map);

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "leaflet.motion",
"version": "0.1.8",
"version": "0.2",
"keywords": [
"leaflet.js",
"browser",
Expand Down
2 changes: 1 addition & 1 deletion src/leaflet.motion.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ L.Motion.Animate = {
var baseRotationAngle = this.__marker._icon.children[0].getAttribute("motion-base");
if(baseRotationAngle){
this.__marker._icon.children[0].style.transform = "rotate(" + baseRotationAngle + "deg)";
}
}
}

if (this.motionOptions.auto) {
Expand Down
75 changes: 55 additions & 20 deletions src/leaflet.motion.utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@
**/

L.Motion.Utils = {
/**
Attaches distances precalculated to current set of LatLng
@param {L.Map} map Leaflet map to be calculate distances
@param {Array<L.LatLng>|L.PolyLine} latlngs Set of geographical points
@returns {Array<L.LatLng>|L.PolyLine} latlngs Set of geographical points with attached distances
*/
attachDistances: function(map, latLngs) {
if (latLngs.length > 1) {
for (var i = 1; i < latLngs.length; i++) {
latLngs[i - 1].distanceToNextPoint = map.distance(latLngs[i - 1], latLngs[i]);
}
}

return latLngs;
},

/**
Returns the coordinate of the point located on a line at the specified ratio of the line length.
@param {L.Map} map Leaflet map to be used for this method
Expand All @@ -14,11 +30,22 @@ L.Motion.Utils = {
*/
interpolateOnLine: function (map, latLngs, ratio) {
latLngs = (latLngs instanceof L.Polyline) ? latLngs.getLatLngs() : latLngs;
var n = latLngs.length;
if (n < 2) {
if (latLngs.length < 2) {
return null;
}

var allDistancesCalculated = true;
for (var d = 0; d < latLngs.length - 1; d++) {
if (!latLngs[d].distanceToNextPoint) {
allDistancesCalculated = false;
break;
}
}

if (!allDistancesCalculated) {
this.attachDistances(map, latLngs);
}

// ensure the ratio is between 0 and 1;
ratio = Math.max(Math.min(ratio, 1), 0);

Expand All @@ -28,47 +55,41 @@ L.Motion.Utils = {
predecessor: -1
};
}

if (ratio == 1) {
return {
latLng: latLngs[latLngs.length -1] instanceof L.LatLng ? latLngs[latLngs.length -1] : L.latLng(latLngs[latLngs.length -1]),
predecessor: latLngs.length - 2
};
}

// project the LatLngs as Points,
// and compute total planar length of the line at max precision
var maxzoom = map.getMaxZoom();
if (maxzoom === Infinity)
maxzoom = map.getZoom();
var pts = [];
var lineLength = 0;
for(var i = 0; i < n; i++) {
pts[i] = map.project(latLngs[i], maxzoom);
if(i > 0)
lineLength += pts[i-1].distanceTo(pts[i]);
// get full line length between points
var fullLength = 0;
for (var dIndex = 0; dIndex < latLngs.length - 1; dIndex++) {
fullLength += latLngs[dIndex].distanceToNextPoint;
}

var ratioDist = lineLength * ratio;
// Calculate expected ratio
var ratioDist = fullLength * ratio;

// follow the line segments [ab], adding lengths,
// until we find the segment where the points should lie on
var cumulativeDistanceToA = 0, cumulativeDistanceToB = 0;
for (var i = 0; cumulativeDistanceToB < ratioDist; i++) {
var pointA = pts[i], pointB = pts[i+1];
var pointA = latLngs[i], pointB = latLngs[i+1];

cumulativeDistanceToA = cumulativeDistanceToB;
cumulativeDistanceToB += pointA.distanceTo(pointB);
cumulativeDistanceToB += pointA.distanceToNextPoint;
}

if (pointA == undefined && pointB == undefined) { // Happens when line has no length
var pointA = pts[0], pointB = pts[1], i = 1;
var pointA = latLngs[0], pointB = latLngs[1], i = 1;
}

// compute the ratio relative to the segment [ab]
var segmentRatio = ((cumulativeDistanceToB - cumulativeDistanceToA) !== 0) ? ((ratioDist - cumulativeDistanceToA) / (cumulativeDistanceToB - cumulativeDistanceToA)) : 0;
var interpolatedPoint = this.interpolateOnPointSegment(pointA, pointB, segmentRatio);
return {
latLng: map.unproject(interpolatedPoint, maxzoom),
latLng: this.interpolateOnLatLngSegment(pointA, pointB, segmentRatio),
predecessor: i-1
};
},
Expand All @@ -87,14 +108,28 @@ L.Motion.Utils = {
);
},

/**
Returns the LatLng located on a segment at the specified ratio of the segment length.
@param {L.LatLng} pA coordinates of LatLng A
@param {L.LatLng} pB coordinates of LatLng B
@param {Number} the length ratio, expressed as a decimal between 0 and 1, inclusive.
@returns {L.LatLng} the interpolated LatLng.
*/
interpolateOnLatLngSegment: function (pA, pB, ratio) {
return L.latLng(
(pA.lat * (1 - ratio)) + (ratio * pB.lat),
(pA.lng * (1 - ratio)) + (ratio * pB.lng)
);
},

/**
@param {LatLng[]} linePoints of coordinates
@return {Number} distance in meter
*/
distance: function(linePoints){
var distanceInMeter = 0;
for (var i = 1; i < linePoints.length; i++) {
distanceInMeter += linePoints[i].distanceTo(linePoints[i - 1]);
distanceInMeter += map.distance(linePoints[i], linePoints[i - 1]);
}

return distanceInMeter;
Expand Down

0 comments on commit 1bf9cf8

Please sign in to comment.