Search code examples
javascriptgoogle-maps-api-3marker

Marker + Label rotation - Google Maps API v3


I'm using an SVG path as marker icon and am trying to rotate it based on the direction it's heading. Icon rotates properly, but i can't seem to align the label once icon is rotated. Is there a way to do that?

Rotating Labels

As you can see the stationary marker (5060) is not being rotated and thus i can align the label in the center, but when i rotate it based on heading direction it uses bottom left corner as anchor and not the center. Also the label itself is not rotating, just the image (1705, 784).

var ArrowIcon = {
    path: path,//SVG path based on status - moving or stationary
    fillColor: 'rgb(79, 151, 240)',
    labelOrigin: labelOrigin, 

    //The SVGs are different to scale and shape 
    //that's why i need different origin for the label

    fillOpacity: 1,
    scale: scale, //Again because different SVGs
    strokeColor: 'white',
    strokeWeight: 1,
    rotation: rotation,
}

var Marker = new google.maps.Marker({
    position: new google.maps.LatLng(Vehicle.Latitude, Vehicle.Longitude),
    map: TrackingMap,
    title: Vehicle.Name,
    label: {text: Vehicle.Name, color: 'white', fontSize: fontSize, fontWeight: 'bold', fontFamily: '"Roboto", sans-serif'},
    content: Vehicle.Name,
    icon: ArrowIcon,
    // anchor: new google.maps.Point(500,500), 
    // this just moves the whole marker, doesn't affect rotation
});

UPDATE:

Working JSFiddle example


Solution

  • To keep the text on the icon, you need to set the labelOrigin appropriately. For your arrow (at least the one in the fiddle), the value of (20,30) works for me:

    var icon = {
      path: path,
      fillColor: 'rgb(79, 151, 240)',
      labelOrigin: new google.maps.Point(25,30), // labelOrigin,
      fillOpacity: 1,
      scale: scale,
      strokeColor: 'white',
      strokeWeight: 1,
      rotation: rotation,
    }
    var Marker = new google.maps.Marker({
      position: new google.maps.LatLng(Vehicle.Latitude, Vehicle.Longitude),
      map: TrackingMap,
      title: Vehicle.Name,
      label: {
        text: Vehicle.Name,
        color: 'white',
        fontSize: fontSize,
        fontWeight: 'bold',
        fontFamily: '"Roboto", sans-serif',
        labelClass: 'TrackingMapLabel',
        background: 'blue'
      },
    
      icon: icon,
      // anchor: new google.maps.Point(500,500),
    });
    

    proof of concept fiddle

    screen shot of rotated icon with text

    code snippet:

    var VehicleList = [{
      Name: "76",
      Latitude: 37.020423,
      Longitude: -94.534732,
      Location: "I-44, Joplin, MO 64804, USA",
      ActivityDateTime: "2017-06-26T07:24:09.167",
      FullActivity: {
        ActivityDateTime: "2017-06-26T07:24:09.167",
        Latitude: 37.020423,
        Longitude: -94.534732,
        GPSValid: true,
        OnSiteTime: 4846,
        Location: "I-44, Joplin, MO 64804, USA",
        IgnitionOn: true,
        HDG: 216,
        Speed: 111,
        EventSubType: "SMDP_EVENT_TIME_OR_DISTANCE",
        IncrementalDistance: "9.4",
        ODOMeter: "112580.203125",
        TripDistance: "135.2",
        ReceivedDateTime: "2017-06-26T07:24:04.477",
        CustomType: -1,
        MaxSpeed: 111,
        IsUnauthorised: false,
        HDOP: "0.80",
        NumSatellites: 11,
        CustomDescription: "",
        CustomData: "",
        OffRoadMetres: 122.90157756779,
        DegreesBearing: 61,
        LocationType: 1,
        NamedArea: "Undefined",
        EventPriority: "Low",
        Version: 0,
        Private: false,
        CommunicationChannel: "Cellular",
        EventTypeDescription: "Timed Update"
      }
    }];
    
    
    var TrackingMap;
    var TrackingMapCenter = {
    
      lat: 37.020423,
      lng: -94.534732
    };
    var TrackingMapZoom = 5;
    
    function initTrackingMap() {
      TrackingMap = new google.maps.Map(document.getElementById('tracking-map'), {
        center: TrackingMapCenter,
        zoom: TrackingMapZoom,
        mapTypeId: 'hybrid'
      });
    }
    initTrackingMap();
    
    
    function SetMarkers(VehicleList) {
      for (i = 0; i < VehicleList.length; i++) {
        Vehicle = VehicleList[i];
        var DT = Vehicle.ActivityDateTime;
        var Offset = moment(DT).format('ZZ');
        Offset = parseInt(Math.abs(Offset.substring(0, Offset.length - 2)));
        // console.log(moment(DT).add(Offset ,'h').format('MMM D, HH:mm:ss'));
        var Speed = (Vehicle.FullActivity.Speed <= 0) ? 0 : (Vehicle.FullActivity.Speed / 1.60934).toFixed(0);
        var Directon = '<i class="fa fa-arrow-up" style="transform: rotate(' + Vehicle.FullActivity.HDG + 'deg); width:15px;margin:2px;" aria-hidden="true"></i>';
        var contentString = '<b>Truck# ' + Vehicle.Name + '</b>' + '<br /><i class="fa fa-map-marker" style="width:15px;margin:2px;"></i>' + Vehicle.Location + '<br /><i class="fa fa-clock-o" style="width:15px;margin:2px;"></i>' + moment(DT).subtract(Offset, 'h').format('MMM D, HH:mm:ss') + '<br /><i class="fa fa-comment" style="width:15px;margin:2px;"></i>' + Vehicle.FullActivity.EventTypeDescription + '<br /><i class="fa fa-tachometer" style="width:15px;margin:2px;"></i>' + Speed + ' MPH'
          // +'<br />Direction: '+Directon
          +
          '<br /><div class="input-group" style="max-width: 200px;padding:5px 0;"><input type="text" class="form-control input-sm" placeholder="Get directions"/> <div class="input-group-addon btn-sm" style="cursor: pointer;" onclick="GetDirections_TrackingMap($(this),\'' + Vehicle.Location + '\');">Go!</div></div>';
        var infowindow = new google.maps.InfoWindow({
          content: contentString
        });
        var pathArrow = 'M 1.958 11.5 h 33.531 c 0.444 0 0.875 0.151 1.221 0.428 l 17.556 14.045 c 0.978 0.783 0.978 2.271 0 3.053 L 36.71 43.072 c -0.347 0.277 -0.777 0.428 -1.221 0.428 H 1.958 C 0.877 43.5 0 42.623 0 41.542 l 0 -28.084 C 0 12.377 0.877 11.5 1.958 11.5 Z';
        var pathArrowScale = 0.6;
        var pathCircle = 'M 409.133 109.203 c -19.608 -33.592 -46.205 -60.189 -79.798 -79.796 C 295.736 9.801 259.058 0 219.273 0 c -39.781 0 -76.47 9.801 -110.063 29.407 c -33.595 19.604 -60.192 46.201 -79.8 79.796 C 9.801 142.8 0 179.489 0 219.267 c 0 39.78 9.804 76.463 29.407 110.062 c 19.607 33.592 46.204 60.189 79.799 79.798 c 33.597 19.605 70.283 29.407 110.063 29.407 s 76.47 -9.802 110.065 -29.407 c 33.593 -19.602 60.189 -46.206 79.795 -79.798 c 19.603 -33.596 29.403 -70.284 29.403 -110.062 C 438.533 179.485 428.732 142.795 409.133 109.203 Z';
        var pathCircleScale = 0.06;
        var pathSquare = 'M 414.41 24.123 C 398.333 8.042 378.963 0 356.315 0 H 82.228 C 59.58 0 40.21 8.042 24.126 24.123 C 8.045 40.207 0.003 59.576 0.003 82.225 v 274.084 c 0 22.647 8.042 42.018 24.123 58.102 c 16.084 16.084 35.454 24.126 58.102 24.126 h 274.084 c 22.648 0 42.018 -8.042 58.095 -24.126 c 16.084 -16.084 24.126 -35.454 24.126 -58.102 V 82.225 C 438.532 59.576 430.49 40.204 414.41 24.123 Z';
        var pathSquareScale = 0.06;
        var path = (Vehicle.FullActivity.Speed > 0) ? pathArrow : (Vehicle.FullActivity.IgnitionOn) ? pathCircle : pathSquare;
        var scale = (Vehicle.FullActivity.Speed > 0) ? pathArrowScale : (Vehicle.FullActivity.IgnitionOn) ? pathCircleScale : pathSquareScale;
        var rotation = (Vehicle.FullActivity.Speed > 0) ? -90 + Vehicle.FullActivity.HDG : (Vehicle.FullActivity.IgnitionOn) ? 0 : 0;
        var labelOrigin = (Vehicle.FullActivity.Speed > 0) ? new google.maps.Point(0, 0) : (Vehicle.FullActivity.IgnitionOn) ? new google.maps.Point(220, 220) : new google.maps.Point(220, 220);
        var fontSize = (Vehicle.FullActivity.Speed > 0) ? '12px' : (Vehicle.FullActivity.IgnitionOn) ? '10px' : '10px';
    
        var icon = {
          path: path,
          fillColor: 'rgb(79, 151, 240)',
          labelOrigin: new google.maps.Point(25, 30), // labelOrigin,
          fillOpacity: 1,
          scale: scale,
          strokeColor: 'white',
          strokeWeight: 1,
          rotation: rotation,
        }
    
        var Marker = new google.maps.Marker({
          position: new google.maps.LatLng(Vehicle.Latitude, Vehicle.Longitude),
          map: TrackingMap,
          title: Vehicle.Name,
          label: {
            text: Vehicle.Name,
            color: 'white',
            fontSize: fontSize,
            fontWeight: 'bold',
            fontFamily: '"Roboto", sans-serif',
            labelClass: 'TrackingMapLabel',
            background: 'blue'
          },
    
          icon: icon,
          // anchor: new google.maps.Point(500,500),
        });
        google.maps.event.addListener(Marker, 'click', (function(Marker, contentString, infowindow) {
          return function() {
            infowindow.setContent(contentString);
            infowindow.open(TrackingMap, Marker);
          };
        })(Marker, contentString, infowindow));
        setInterval(function() {
          var icon = Marker.getIcon();
          icon.rotation += 10;
          icon.rotation %= 360;
          Marker.setIcon(icon);
        }, 1000);
      }
    }
    SetMarkers(VehicleList);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places,geometry&language=en&region=EN"></script>
    <div class="google-map " id="tracking-map" style="height: 525px">
    </div>