0

I'm interested by the script Leaflet motion.

I tried to update the code to add a custom GeoJSON created from QGIS or any tool.

But the current error is :

leaflet.motion.min.js:9 Uncaught TypeError: Cannot read properties of null (reading 'traveledPath')
 at i._motion (leaflet.motion.min.js:9:2842)
 at i.motionStart (leaflet.motion.min.js:9:3960)
 at i.motionStart (leaflet.motion.min.js:9:12135)
 at test14.html:110:26
<!DOCTYPE html>
<html>
 <head>
 <title>Leaflet motion plugin</title>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
 <link rel="stylesheet" href="https://leaflet.github.io/Leaflet.draw/src/leaflet.draw.css"/>
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
 <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.js"></script>
 <script src="https://mappingforyou.eu/javascript/leaflet.ajax.min.js"></script>
 
 <script src="../javascript/leaflet.motion.min.js"></script>
 <style>
 html, body, #map { width: 100%; height: 100%; margin: 0px; padding: 0px;}
 .leaflet-div-icon {
 background: transparent!important;
 border: none!important;
 color: white;
 }
 .red {
 color: red!important;
 }
 </style>
 </head>
 <body>
 <div id="map"></div>
 <script>
 var map = L.map("map").setView([51, 1], 5);
 L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
 attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
 }).addTo(map);
 var options = {
 draw: {
 circle: false, // Turns off this drawing tool
 rectangle: false,
 marker: false,
 circlemarker: false
 }
 };
 
 
 
 var drawControl = new L.Control.Draw(options);
 map.addControl(drawControl);
 map.on(L.Draw.Event.CREATED, function (e) {
 var type = e.layerType,
 layer = e.layer;
 if (type === "polyline") {
 var line = L.motion.polyline(layer.getLatLngs(), {
 color: "orange"
 }, {
 auto: true,
 easing: L.Motion.Ease.swing
 }).motionSpeed(100000).addTo(map);
 }
 if (type === "polygon") {
 L.motion.polygon(layer.getLatLngs(), {
 color: "red",
 fill: true,
 fillOpacity: 0.4
 },{
 auto: true
 }, {
 removeOnEnd: true,
 icon: L.divIcon({className:"red", html: "<i class='fa fa-superpowers fa-spin fa-2x' aria-hidden='true' motion-base='0'></i>", iconSize: L.point(24, 24), iconAnchor: L.point(5, 22)})
 }).motionDuration(10000).addTo(map);
 }
 });
 
 
 var geoJsonData ={"type":"FeatureCollection","features":[{"properties":{"name":""},"type":"Feature","geometry":{"type":"LineString","coordinates":[[-7.271833,51.09715],[0.15577,50.667658],[8.638181,48.79433],[12.703585,45.710102],[9.297436,43.090615],[0.749099,41.036735],[-4.393088,41.548214]]}}]};
 
 
 
 
 var seqGroup = L.motion.seq([
 L.motion.polyline(geoJsonData, {
 color: "orangered"
 }, {
 easing: L.Motion.Ease.easeInOutQuad
 }, {
 removeOnEnd: false,
 icon: L.divIcon({html: "<i class='fa fa-truck fa-2x fa-flip-horizontal' aria-hidden='true'></i>", iconSize: L.point(27.5, 24)})
 }).motionDuration(8000)
 ]).addTo(map);
 seqGroup.on("click", function(){
 seqGroup.motionStart();
 });
 seqGroup.on("dblclick", function(e){
 seqGroup.motionToggle();
 });
 setTimeout(function () {
 seqGroup.motionStart();
 }, 1000);
 </script>
 </body>
</html>

I'm looking for a way to create a simple line like the one of this json.parse.

Can you help?

Alternatively, I'd like to feed Leaflet Motion with an external geojson file, that would gave the same result.

PolyGeo
65.5k29 gold badges115 silver badges350 bronze badges
asked Jun 7, 2022 at 14:38
6
  • If I understand you correctly, you have GeoJSON array of point geometries? Commented Jun 7, 2022 at 16:49
  • It was first a line when I drawed it on Qgis. Then I may have turned it into point geometries to try if it felt better like this. Commented Jun 7, 2022 at 16:52
  • @TomazicM I updated the code. this is a line Commented Jun 7, 2022 at 17:47
  • So your GeoJSON is not collection of points but line string feature? Does it really have only two points? Makes no sense for motion. Commented Jun 7, 2022 at 18:06
  • @TomazicM at the end, it wouldn't have only 2 points but hundreds of them, I just wanted to simplify the code for troubleshooting, initially, they were a lot Commented Jun 7, 2022 at 18:08

2 Answers 2

3

All you have to do is extract line string coordinates from geoJsonData and store them in some array, let's say dataCoords, and flip coordinates while doing that, since Leaflet expects [lat, lng] coordinate order, while GeoJSON has [lng, lat] order:

dataCoords = [];
geoJsonData.features[0].geometry.coordinates.forEach(function(coords) {
 dataCoords.push([coords[1], coords[0]]);
});

Array dataCoords can then be used as input to L.motion.polyline:

var seqGroup = L.motion.seq([
 L.motion.polyline(dataCoords, {
 color: "orangered"
 }, {
 easing: L.Motion.Ease.easeInOutQuad
 }, {
 removeOnEnd: false,
 icon: L.divIcon({html: "<i class='fa fa-truck fa-2x fa-flip-horizontal' aria-hidden='true'></i>", iconSize: L.point(27.5, 24)})
 }).motionDuration(8000)
]).addTo(map);
answered Jun 7, 2022 at 18:30
0
2

remove the following line.

var Json2 = JSON.parse(geoJsonData)

JSON.parse extracts a dictionary from a string. Thus you do not need it here.

Edit: To your new inquiry here's another approach. (Tested)

<!DOCTYPE html>
<html>
 <head>
 <title>Leaflet motion plugin</title>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
 <link rel="stylesheet" href="https://leaflet.github.io/Leaflet.draw/src/leaflet.draw.css"/>
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
 <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.js"></script>
 <script src="https://mappingforyou.eu/javascript/leaflet.ajax.min.js"></script>
 
 <script src="../javascript/leaflet.motion.min.js"></script>
 <style>
 html, body, #map { width: 100%; height: 100%; margin: 0px; padding: 0px;}
 .leaflet-div-icon {
 background: transparent!important;
 border: none!important;
 color: white;
 }
 .red {
 color: red!important;
 }
 </style>
 </head>
 <body>
 <div id="map"></div>
 <script>
 var map = L.map("map").setView([51, 1], 5);
 L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
 attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
 }).addTo(map);
 var options = {
 draw: {
 circle: false, // Turns off this drawing tool
 rectangle: false,
 marker: false,
 circlemarker: false
 }
 };
 
 
 
 var drawControl = new L.Control.Draw(options);
 map.addControl(drawControl);
 map.on(L.Draw.Event.CREATED, function (e) {
 var type = e.layerType,
 layer = e.layer;
 if (type === "polyline") {
 var line = L.motion.polyline(layer.getLatLngs(), {
 color: "orange"
 }, {
 auto: true,
 easing: L.Motion.Ease.swing
 }).motionSpeed(100000).addTo(map);
 }
 if (type === "polygon") {
 L.motion.polygon(layer.getLatLngs(), {
 color: "red",
 fill: true,
 fillOpacity: 0.4
 },{
 auto: true
 }, {
 removeOnEnd: true,
 icon: L.divIcon({className:"red", html: "<i class='fa fa-superpowers fa-spin fa-2x' aria-hidden='true' motion-base='0'></i>", iconSize: L.point(24, 24), iconAnchor: L.point(5, 22)})
 }).motionDuration(10000).addTo(map);
 }
 });
 
 
 var geoJsonData ={"type":"FeatureCollection","features":[{"properties":{"name":""},"type":"Feature","geometry":{"type":"LineString","coordinates":[[-7.271833,51.09715],[0.15577,50.667658],[8.638181,48.79433],[12.703585,45.710102],[9.297436,43.090615],[0.749099,41.036735],[-4.393088,41.548214]]}}]};
 var coordinates = geoJsonData.features[0].geometry.coordinates
 
 
 
 
 var seqGroup = L.motion.seq([
 L.motion.polyline(coordinates, {
 color: "orangered"
 }, {
 easing: L.Motion.Ease.easeInOutQuad
 }, {
 removeOnEnd: false,
 icon: L.divIcon({html: "<i class='fa fa-truck fa-2x fa-flip-horizontal' aria-hidden='true'></i>", iconSize: L.point(27.5, 24)})
 }).motionDuration(8000)
 ]).addTo(map);
 seqGroup.on("click", function(){
 seqGroup.motionStart();
 });
 seqGroup.on("dblclick", function(e){
 seqGroup.motionToggle();
 });
 setTimeout(function () {
 seqGroup.motionStart();
 }, 1000);
 </script>
 </body>
</html>
answered Jun 7, 2022 at 17:57
1
  • thanks , I updated the code but I have Uncaught TypeError: Cannot read properties of null (reading 'traveledPath') Commented Jun 7, 2022 at 18:07

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.