Search code examples
leafletmarkergoogle-polyline

marker with polyline while dragging the marker using leaflet


Hi I have connection between marker with polyline like this Image . I am attaching a sample here.enter image description here

How Can I make drag possible that when I drag the the marker with polyline.

example , If I drag the marker 3 it should also update the polyline point and where ever I put the marker 3 polyline should connect with marker 3.

I need this type of drag event that can update the polyline also when dragging the marker.

I am using leaflet for this purpose but still unable to solve the dragging logic of marker with polyline.

Here is the sample code I am using

$http.get("db/getConnectionData.php").then(function (response) {


$scope.links1 = response.data.records;


// $scope.showArrow();
   angular.forEach($scope.links1, function(value, i) {
        var source_panoId = $scope.links1[i].s_panoId;
        var dest_panoId   = $scope.links1[i].d_panoId;
        var sPanoID      = $scope.links1[i].sourcePano_id;
        var dPpanoID     = $scope.links1[i].destPano_id;


          angular.forEach($scope.panoramas, function(value, index) {
              if($scope.panoramas[index].panoId == source_panoId){
                   if($scope.links.indexOf($scope.panoramas[index])== -1){
                         $scope.links.push($scope.panoramas[index]);
                     }
                    var SlatLang = $scope.panoramas[index].project_latLng ;
                    var SLatLngArr = SlatLang.split(",");
                    var Slat  = parseFloat(SLatLngArr[0]);
                    var Slang = parseFloat(SLatLngArr[1]);
                    var polypoint1 = [Slat, Slang];

                angular.forEach($scope.panoramas, function(value, index1) {
                   if($scope.panoramas[index1].panoId == dest_panoId){         
                       if($scope.links.indexOf($scope.panoramas[index1])== -1){                                      
                            $scope.links.push($scope.panoramas[index1]);
                        }
                        var DlatLang = $scope.panoramas[index1].project_latLng ;
                        var DLatLngArr = DlatLang.split(",");
                        var Dlat  = parseFloat(DLatLngArr[0]);
                        var Dlang = parseFloat(DLatLngArr[1]);
                        var polypoint2 = [Dlat, Dlang];

                       // Draw seperate polyline for each connection
                        polyline = L.polyline([[Slat, Slang],[Dlat, Dlang]],
                                              {
                                                color: 'blue',
                                                weight: 5,
                                                opacity: .7,
                                              }
                                              ).addTo(map);

                                    $scope.polycoords.push(polyline);


                                }

                            });


                        }

                    });

Here is the code that I am using to make drag of marker with polyline

angular.forEach($scope.panoramas, function(value, index4){

$scope.markers[index4].on('dragstart', function(e){

            var latlngs = polyline.getLatLngs(),
                latlng = $scope.markers[index4].getLatLng();

            for (var i = 0; i < latlngs.length; i++) {
                if (latlng.equals(latlngs[i])) {
                    this.polylineLatlng = i;
                }
            }



        });//dragstart

        $scope.markers[index4].on('drag', function(e){

          var latlngs = polyline.getLatLngs(),
              latlng = $scope.markers[index4].getLatLng();
              latlngs.splice(this.polylineLatlng, 1, latlng);
              polyline.setLatLngs(latlngs);
        });//drag

        $scope.markers[index4].on('dragend', function(e){
          delete this.polylineLatlng;
        });//dragEnd

    });

Solution

  • First, when creating the marker, remember to pass the draggable option as true, like this:

    var marker = L.marker(latLng, { draggable: true });
    

    Now, check which drag event you want to attach a listener to and then call the redraw function of the polyline inside the callback, like this:

    // var polyline defined somewhere
    marker.on('drag', function (e) {
        polyline.redraw();
    });
    

    If this doesn't work, please provide sample code so we can work around with it.

    Edit

    You also need to change the coordinates of the polyline, otherwise redraw will do nothing. Check out this answer on SO and see if it fits your needs.

    Edit 2

    You're using an array of polylines while the answer just uses one polyline which has the array of coordinates, so in your case you need to use two loops to accomplish the same task. You can make this faster and maybe use an object as a lookup table to get the right polyline for each marker, for example, like this:

    var table = {};
    // ...
    table[marker] = polyline;
    

    Then later you can get the polyline used for each marker. But anyway, here's what I think would work in your case the way it is in the sample (it was a little hard to understand but I hope it works for you).

    I don't know where you are putting the second part of your sample (the event handlers) but I assume it's not inside the double loop that is creating the polylines, right? So this is what I came up with:

    marker.on('dragstart', function (e) {
        var markerLatLng = marker.getLatLng();
    
        this.polylineLatLngs = [];
        for (var i = 0; i < $scope.polycoords.length; i++) {
            var polyline = $scope.polycoords[i];
            var latLngs = polyline.getLatLngs()
    
            for (var j = 0; j < latLngs.length; j++) {
                if (markerLatLng.equals(latLngs[j])) {
                    this.polylineLatLngs.push([i, j]);
                }
            }
        }
    });
    
    marker.on('drag', function (e) {
        for (var i = 0; i < this.polylineLatLngs.length; i++) {
            var polyline = $scope.polycoords[this.polylineLatLngs[i][0]];
            var latLngs = polyline.getLatLngs();
            var markerLatLng = marker.getLatLng();
    
            latLngs.splice(this.polylineLatLngs[i][1], 1, markerLatLng);
            polyline.setLatLngs(latLngs);
        }
    });