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.

6
  • If I understand you correctly, you have GeoJSON array of point geometries?
    – TomazicM
    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.
    – Vincent Dc
    Commented Jun 7, 2022 at 16:52
  • @TomazicM I updated the code. this is a line
    – Vincent Dc
    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.
    – TomazicM
    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
    – Vincent Dc
    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);
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>
1
  • thanks , I updated the code but I have Uncaught TypeError: Cannot read properties of null (reading 'traveledPath')
    – Vincent Dc
    Commented Jun 7, 2022 at 18:07

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.