I have an app working in node.js that locates a user and plots their location on a leaflet map. When others connect it shows them too. It keeps their marker live as long as they move the mouse.

I would like to change a couple of things but not sure where to start:

  1. Update the users marker when they move.
  2. Keep the marker live as long as the connection is live, not as long as they are moving the mouse or moving in general as they may stop on the jorney.

I know I can use the watch feature but not sure where to add it.I will include the application.js code with is where the map locate and placing the marker code is.

The application.js

$(function() {
    // generate unique user id
    var userId = Math.random().toString(16).substring(2,15);
    var socket = io.connect('/');
    socket.emit('little_newbie', username);
    var map;


    var info = $('#infobox');
    var doc = $(document);

    // custom marker's icon styles
    var tinyIcon = L.Icon.extend({
        options: {
            shadowUrl: '../assets/marker-shadow.png',
            iconSize: [25, 39],
            iconAnchor:   [12, 36],
            shadowSize: [41, 41],
            shadowAnchor: [12, 38],
            popupAnchor: [0, -30]
        }
    });
    var redIcon = new tinyIcon({ iconUrl: '../assets/marker-red.png' });
    var yellowIcon = new tinyIcon({ iconUrl: '../assets/marker-yellow.png' });

    var sentData = {};
    var connects = {};
    var markers = {};
    var active = false;

    socket.on('load:coords', function(data) {
        if (!(data.id in connects)) {
            setMarker(data);
        }

        connects[data.id] = data;
        connects[data.id].updated = $.now();
    });

    // check whether browser supports geolocation api
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(positionSuccess, positionError, { enableHighAccuracy: true });
    } else {
        $('.map').text('Your browser is out of fashion, there\'s no geolocation!');
    }

    function positionSuccess(position) {
        var lat = position.coords.latitude;
        var lng = position.coords.longitude;
        var acr = position.coords.accuracy;


        // mark user's position
        var userMarker = L.marker([lat, lng], {
            icon: redIcon
        });
        // uncomment for static debug
        // userMarker = L.marker([51.45, 30.050], { icon: redIcon });

        // load leaflet map

    map = L.map('map').fitWorld();

    L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
            '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        id: 'mapbox.streets'
    }).addTo(map);

        userMarker.addTo(map);
        userMarker.bindPopup('<p>You are here ' + username + '</p>').openPopup();

        var emit = $.now();
        // send coords on when user is active
        doc.on('mousemove', function() {
            active = true;

            sentData = {
                id: userId,
                active: active,
                coords: [{
                    lat: lat,
                    lng: lng,
                    acr: acr,
                    name: username
                }]
            };

            if ($.now() - emit > 1) {
                socket.emit('send:coords', sentData);
                emit = $.now();
            }
        });
    }

    doc.bind('mouseup mouseleave', function() {
        active = false;
    });

    // showing markers for connections
    function setMarker(data) {
        for (var i = 0; i < data.coords.length; i++) {

            var num = +$("#count").text() + 1;
            $("#count").text(num);

            var marker = L.marker([data.coords[i].lat, data.coords[i].lng], { icon: yellowIcon }).addTo(map);
            marker.bindPopup('<p>One more external user is here!</p>' + data.coords[i].name);
            markers[data.id] = marker;
        }
    }

    // handle geolocation api errors
    function positionError(error) {
        var errors = {
            1: 'Authorization fails', // permission denied
            2: 'Can\'t detect your location', //position unavailable
            3: 'Connection timeout' // timeout
        };
        showError('Error:' + errors[error.code]);
    }

    function showError(msg) {
        info.addClass('error').text(msg);

        doc.click(function() {
            info.removeClass('error');
        });
    }

    // delete inactive users every 15 sec
    setInterval(function() {
        for (var ident in connects){
            if ($.now() - connects[ident].updated > 200000) {
            var num = +$("#count").text() - 1;
            $("#count").text(num);
                delete connects[ident];
                map.removeLayer(markers[ident]);
            }
        }
    }, 15000);
});
  • Cool question! If I interpret Geolocation.watchPosition() correctly, you can bind it to each of your users and it will call the success function whenever your user moves. You would use a similar function there as what is now your onMousemove function. – Stefan Nov 20 at 7:42
  • I assume the clients connect via a browser on a portable device? I think that an operating system such as Android can hibernate apps that are sent to the background. So when your user leaves the browser the connection might be disconnected. – Stefan Nov 20 at 7:48
  • Hi Stefan, yes via a browser at the moment and what you mention at the beginning is what I am trying to achieve but keep hitting brick walls! any help would be great – larry chambers Nov 20 at 10:12
  • You have to post code that you tried to implement and that doesn't work. If there are error messages, include those too. – Stefan Nov 20 at 12:06
  • I have changed it that many times, the closest I got to it working was adding a new marker when user moved but it kept the old one and stopped after about 3 new markers. So what I need for now is just to keep them live whilst they are connected and remove marker when they have disconnected. How do I do this? Do I have to create arrays of connected users or is there an easier way?? – larry chambers Nov 20 at 18:32

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.