Rotating image / marker image on Google map V3

2019-01-03 10:11发布

How could I rotate an image (marker image) on a Google map V3?

  • There is an excellent example for V2 here, exactly doing what I need. But for GMap2! They do it with a rotating canvas.
  • Image rotating with JS / JQuery is frequently used, there are multiple answers about this. But how could I apply this to my maps image?
  • One mentioned approach is to have different images for different angles and to switch among them - this is NOT what I want. I do not like to have so many images, I want to rotate by code.

Remark: There are similar questions, but all for V2 and not V3 (as far I can tell). I need it for V3.

14条回答
2楼-- · 2019-01-03 10:52

How could I rotate an image (marker image) on a Google map V3?

I had the same problem and I solved it with the next code:

var gmap;
NgMap.getMap(function(map){
    gmap = map;
});

I suppose that you have a variable with the icon, for example:

var imagePath = 'img/customMarker.png';

First, we need to create our marker options:

var markerOptions = {
    location: [x, y],
    title:'some text',
    draggable: true,
    .
    .
    .
    icon: imagePath
};

Let's create a marker:

var marker = new google.maps.Marker(markerOptions);

And we have to set the map:

marker.setMap(map);

Now if you want to rotate the image you need to do the next:

  • Change the imagePath variable's value to 'img/customMarker.png#yourId'
  • Set rotation value with css (e.g. with JQuery)

Let's see

imagePath = 'img/customMarker.png#markerOne';

$('img[src="img/customMarker.png#markerOne"]').css({
     'transform': 'rotate(45deg)'
});

Of course you can do it fancier:

function rotateMarker(selector, degree){
     $('img[src="img/customMarker.png#'+selector+'"]').css({
         'transform': 'rotate('+degree+'deg)'
     });
}

And your call:

rotateMarker('markerOne', 45);

That's all.

I hope it could be helpful.

查看更多
趁早两清
3楼-- · 2019-01-03 10:53

You did not state it in your question, but I am assuming that you want this rotation in relation to a line between point a and point b, which would be their path. In order to make a google svg icon that can be rotated, you will want to use the google symbol class object to define the properties of your marker symbol. This does not use a full .svg file, but only the d attribute of the path. Note that the google symbol class can only take one path per marker.

Additional attributes for color, stroke, width, opacity, etc. may be set after the marker has been created with javascript (updating the marker object properties directly), or with CSS (updating the marker properties by adding and removing classes).

As an example, the following will create an arrow marker that can be dragged, and it will be rotated around the point on the map that is the lat and long for the marker even after it is moved.

The HTML

<body id="document_body" onload="init();">
  <div id="rotation_control">
    Heading&deg;<input id="rotation_value" type="number" size="3" value="0" onchange="setRotation();" />
  </div>
  <div id="map_canvas"></div>
</body>

The CSS (yes,verbose... I hate ugly)

#document_body {
    margin:0;
    border: 0;
    padding: 10px;
    font-family: Arial,sans-serif;
    font-size: 14px;
    font-weight: bold;
    color: #f0f9f9;
    text-align: center;
    text-shadow: 1px 1px 1px #000;
    background:#1f1f1f;
  }
  #map_canvas, #rotation_control {
    margin: 1px;
    border:1px solid #000;
    background:#444;
    -webkit-border-radius: 4px;
       -moz-border-radius: 4px;
            border-radius: 4px;
  }
  #map_canvas { 
    width: 100%;
    height: 360px;
  }
  #rotation_control { 
    width: auto;
    padding:5px;
  }
  #rotation_value { 
    margin: 1px;
    border:1px solid #999;
    width: 60px;
    padding:2px;
    font-weight: bold;
    color: #00cc00;
    text-align: center;
    background:#111;
    border-radius: 4px;
  }

The Javascript (in plain vanilla flavor for understanding core concepts)

var map, arrow_marker, arrow_options;
var map_center = {lat:41.0, lng:-103.0};
var arrow_icon = {
  path: 'M -1.1500216e-4,0 C 0.281648,0 0.547084,-0.13447 0.718801,-0.36481 l 17.093151,-22.89064 c 0.125766,-0.16746 0.188044,-0.36854 0.188044,-0.56899 0,-0.19797 -0.06107,-0.39532 -0.182601,-0.56215 -0.245484,-0.33555 -0.678404,-0.46068 -1.057513,-0.30629 l -11.318243,4.60303 0,-26.97635 C 5.441639,-47.58228 5.035926,-48 4.534681,-48 l -9.06959,0 c -0.501246,0 -0.906959,0.41772 -0.906959,0.9338 l 0,26.97635 -11.317637,-4.60303 c -0.379109,-0.15439 -0.812031,-0.0286 -1.057515,0.30629 -0.245483,0.33492 -0.244275,0.79809 0.0055,1.13114 L -0.718973,-0.36481 C -0.547255,-0.13509 -0.281818,0 -5.7002158e-5,0 Z',
  strokeColor: 'black',
  strokeOpacity: 1,
  strokeWeight: 1,
  fillColor: '#fefe99',
  fillOpacity: 1,
  rotation: 0,
  scale: 1.0
};

function init(){
  map = new google.maps.Map(document.getElementById('map_canvas'), {
    center: map_center,
    zoom: 4,
    mapTypeId: google.maps.MapTypeId.HYBRID
  });
  arrow_options = {
    position: map_center,
    icon: arrow_icon,
    clickable: false,
    draggable: true,
    crossOnDrag: true,
    visible: true,
    animation: 0,
    title: 'I am a Draggable-Rotatable Marker!' 
  };
  arrow_marker = new google.maps.Marker(arrow_options);
  arrow_marker.setMap(map);
}

function setRotation(){
  var heading = parseInt(document.getElementById('rotation_value').value);
  if (isNaN(heading)) heading = 0;
  if (heading < 0) heading = 359;
  if (heading > 359) heading = 0;
  arrow_icon.rotation = heading;
  arrow_marker.setOptions({icon:arrow_icon});
  document.getElementById('rotation_value').value = heading;
}

And the best yet, doing it this way assures the marker is a Google MVC object, giving it all the additional methods provided by the MVC object.

If you must have multi-colored images as your marker, then creating a .png sprite sheet with a rendition of the image at all the angles you want it to be shown, and then problematically select the correct image to use based on the computed bearing between the two points you are using. However,this would not be an SVG image, but a regular marker image.

Hope this helps in making some decisions regarding your map markers.

查看更多
小情绪 Triste *
4楼-- · 2019-01-03 10:54

My js class for solving this problem is:

var RotateIcon = function(options){
    this.options = options || {};
    this.rImg = options.img || new Image();
    this.rImg.src = this.rImg.src || this.options.url || '';
    this.options.width = this.options.width || this.rImg.width || 52;
    this.options.height = this.options.height || this.rImg.height || 60;
    var canvas = document.createElement("canvas");
    canvas.width = this.options.width;
    canvas.height = this.options.height;
    this.context = canvas.getContext("2d");
    this.canvas = canvas;
};
RotateIcon.makeIcon = function(url) {
    return new RotateIcon({url: url});
};
RotateIcon.prototype.setRotation = function(options){
    var canvas = this.context,
        angle = options.deg ? options.deg * Math.PI / 180:
            options.rad,
        centerX = this.options.width/2,
        centerY = this.options.height/2;

    canvas.clearRect(0, 0, this.options.width, this.options.height);
    canvas.save();
    canvas.translate(centerX, centerY);
    canvas.rotate(angle);
    canvas.translate(-centerX, -centerY);
    canvas.drawImage(this.rImg, 0, 0);
    canvas.restore();
    return this;
};
RotateIcon.prototype.getUrl = function(){
    return this.canvas.toDataURL('image/png');
};

Call it like this:

var marker = new google.maps.Marker({
    icon: {
        url: RotateIcon
            .makeIcon(
                'https://ru.gravatar.com/userimage/54712272/b8eb5f2d540a606f4a6c07c238a0bf40.png')
            .setRotation({deg: 92})
            .getUrl()
    }})

See live example here http://jsfiddle.net/fe9grwdf/39/

查看更多
做自己的国王
5楼-- · 2019-01-03 10:55

I was able to solve this pretty easily but using the marker.icon.rotation option pointing to a custom symbol that uses the svg path syntax.

$scope.triangle = {
  path: 'M 0 0 L -35 -100 L 35 -100 z',
  fillColor: '#3884ff',
  fillOpacity: 0.7,
  scale: 1,
  strokeColor: '#356cde',
  rotation: 90,
  strokeWeight: 1

}; 

If using angular-google-maps it is trivial to bind a ui control to change the triangle.rotation.

Like I did with this slider.

<slider  ng-model="triangle.rotation" floor="0" ceiling="359" step="5" precsion="1"></slider>

But you could use a forum too.

here is my plunker http://plnkr.co/edit/x0egXI

查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-01-03 10:57

The easiest way may be to use the rotation property of google.maps.Symbol. Just set it as a property of your icon when creating or updating your marker:

new google.maps.Marker({
  position: map.getCenter(),
  icon: {
    path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
    scale: 7,
    rotation: 193
  },
  map: map
});

Plunker

查看更多
劫难
7楼-- · 2019-01-03 11:00

This is how i implemented my image rotated, I considered the marker in the form of overlay and that overlay is position to the position, Below code will be added .

Without using any additional library it is rotated,And you need to workaround to add click events and mouse events for the overlay, not similar to marker click events.

With googleMap markers customization, there will be addition memory usage in the map. This will also reduce the memory consumption of custom markers in your map.

 <html>
    <head>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <style>html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    #map_canvas {
        height: 100%;
    }
    div.htmlMarker {
        color: red;
        cursor: pointer;
    }

    </style>
    </head>
    <body onload="initialize()">
        <div id="map_canvas"></div>
    </body>

    <script>
    var overlay;

    function initialize() {
        var myLatLng = new google.maps.LatLng(40, -100);
        var mapOptions = {
            zoom: 10,
            center: myLatLng,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        var gmap = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

        function HTMLMarker(lat, lng, rotation) {
            this.lat = lat;
            this.lng = lng;
             this.rotation = rotation;
            this.pos = new google.maps.LatLng(lat, lng);
        }

        HTMLMarker.prototype = new google.maps.OverlayView();
        HTMLMarker.prototype.onRemove = function () {}

        //Initilize your html element here
        HTMLMarker.prototype.onAdd = function () {
            div = document.createElement('DIV');
            div.style.position='absolute';
            div.style.transform='rotate('+this.rotation +'deg)';
            div.style.MozTransform='rotate('+this.rotation +'deg)';
            div.className = "htmlMarker";
           //image source use your own image in src
            div.innerHTML = '<img src="prudvi.png" alt="Mountain View" style="width:25px;height:22px">' ;
            var panes = this.getPanes();
            panes.overlayImage.appendChild(div);
            this.div=div;
        }

        HTMLMarker.prototype.draw = function () {
            var overlayProjection = this.getProjection();
            var position = overlayProjection.fromLatLngToDivPixel(this.pos);
            var panes = this.getPanes();
            this.div.style.left = position.x + 'px';
            this.div.style.top = position.y - 30 + 'px';
        }

        //Added 50 marker with random latlng location and random rotation,
        for (i = 0; i < 50; i++) {
        var PoslatLng = new google.maps.LatLng(myLatLng.lat() + Math.random() - 0.5, myLatLng.lng() + Math.random() - 0.5);
        var htmlMarker = new HTMLMarker(myLatLng.lat() + Math.random() - 0.5,myLatLng.lng() + Math.random() - 0.5, Math.floor(Math.random() * 359));
        htmlMarker.setMap(gmap);
    google.maps.event.addListener(htmlMarker, 'click', function() {
        console.log('clciked')
        gmap.setZoom(8);
        gmap.setCenter(htmlMarker.getPosition());
      });
        }
    }
    </script>
  </html>
查看更多
登录 后发表回答