none
Rotate Custom Image Pushpin RRS feed

  • Question

  • Hi,

    How can i rotate custom image pushpin? Without using canvas?

    Note: V8 Javascript API.
    • Edited by IfThenBreak Thursday, July 21, 2016 1:54 PM
    Thursday, July 21, 2016 1:53 PM

Answers

  • The canvas is your only option. Here is a code sample with a reusable function for creating rotated image pushpins using a canvas.

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <meta charset="utf-8" />
        <script type='text/javascript'
                src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap'
                async defer></script>
        <script type='text/javascript'>
        function GetMap() {
            var map = new Microsoft.Maps.Map('#myMap', {
                credentials: 'Your Bing Maps Key'
            });
    
            createRotatedImagePushpin(map.getCenter(), 'images/ssMap.png', 45, function (pin) {
                map.entities.push(pin);
            });
        }
    
        function createRotatedImagePushpin(location, url, rotationAngle, callback) {
            var img = new Image();
            img.onload = function () {
                var c = document.createElement('canvas');
    
                var rotationAngleRads = rotationAngle * Math.PI / 180;
    
               //Calculate rotated image size.
                c.width = Math.abs(Math.ceil(img.width * Math.cos(rotationAngleRads) + img.height * Math.sin(rotationAngleRads)));
                c.height = Math.abs(Math.ceil(img.width * Math.sin(rotationAngleRads) + img.height * Math.cos(rotationAngleRads)));
    
                var context = c.getContext('2d');
    
                //Move to the center of the canvas.
                context.translate(c.width / 2, c.height / 2);
    
                //Rotate the canvas to the specified angle in degrees.
                context.rotate(rotationAngleRads);
    
                //Draw the image, since the context is rotated, the image will be rotated also.
                context.drawImage(img, -img.width / 2, -img.height / 2);
    
                var pin = new Microsoft.Maps.Pushpin(location, {
                    //Generate a base64 image URL from the canvas.
                    icon: c.toDataURL(),
                    anchor: new Microsoft.Maps.Point(c.width / 2, c.height / 2) //Anchor to center of image.
                });
    
                if (callback) {
                    callback(pin);
                }
            };
    
            //Allow cross domain image editting.
            img.crossOrigin = 'anonymous';
            img.src = url;
        }
        </script>
    </head>
    <body>
        <div id="myMap" style=";width:600px;height:400px;"></div>
    </body>
    </html>


    [Blog] [twitter] [LinkedIn]


    Thursday, July 21, 2016 6:56 PM

All replies

  • The canvas is your only option. Here is a code sample with a reusable function for creating rotated image pushpins using a canvas.

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <meta charset="utf-8" />
        <script type='text/javascript'
                src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap'
                async defer></script>
        <script type='text/javascript'>
        function GetMap() {
            var map = new Microsoft.Maps.Map('#myMap', {
                credentials: 'Your Bing Maps Key'
            });
    
            createRotatedImagePushpin(map.getCenter(), 'images/ssMap.png', 45, function (pin) {
                map.entities.push(pin);
            });
        }
    
        function createRotatedImagePushpin(location, url, rotationAngle, callback) {
            var img = new Image();
            img.onload = function () {
                var c = document.createElement('canvas');
    
                var rotationAngleRads = rotationAngle * Math.PI / 180;
    
               //Calculate rotated image size.
                c.width = Math.abs(Math.ceil(img.width * Math.cos(rotationAngleRads) + img.height * Math.sin(rotationAngleRads)));
                c.height = Math.abs(Math.ceil(img.width * Math.sin(rotationAngleRads) + img.height * Math.cos(rotationAngleRads)));
    
                var context = c.getContext('2d');
    
                //Move to the center of the canvas.
                context.translate(c.width / 2, c.height / 2);
    
                //Rotate the canvas to the specified angle in degrees.
                context.rotate(rotationAngleRads);
    
                //Draw the image, since the context is rotated, the image will be rotated also.
                context.drawImage(img, -img.width / 2, -img.height / 2);
    
                var pin = new Microsoft.Maps.Pushpin(location, {
                    //Generate a base64 image URL from the canvas.
                    icon: c.toDataURL(),
                    anchor: new Microsoft.Maps.Point(c.width / 2, c.height / 2) //Anchor to center of image.
                });
    
                if (callback) {
                    callback(pin);
                }
            };
    
            //Allow cross domain image editting.
            img.crossOrigin = 'anonymous';
            img.src = url;
        }
        </script>
    </head>
    <body>
        <div id="myMap" style=";width:600px;height:400px;"></div>
    </body>
    </html>


    [Blog] [twitter] [LinkedIn]


    Thursday, July 21, 2016 6:56 PM
  • What if I need to change the rotation angle when clicking a button?

    Jim King

    Tuesday, October 15, 2019 1:44 AM
  • Hi Jim,

    Please look at event handling in our Interactive SDK. https://www.bing.com/api/maps/sdk/mapcontrol/isdk/addeventhandler . You should be able to use these methods to take an action based on a click or a Pin or other item as you need.

    Sincerely,

    IoTGirl

    Tuesday, October 15, 2019 9:22 PM
    Owner
  • It's not about the event handler. The key point here is to change the rotation parameter of the icon. Since bing map does not provide an easy way to implement it, I have to write a lot of extra code myself.

    I have successfully accomplish the task(change the rotation of an SVG icon). Here is the pseudo code:

    function draw(svgIcon, fillColor, rotation) {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      ctx.translate(offsetX, offsetY);
      ctx.rotate(rotation * Math.PI / 180);
      ctx.scale(0.6, 0.6);
      ctx.translate(-offsetX, -offsetY);
      ctx.fillStyle = fillColor;
      ctx.fill(new Path2D(svgIcon));
      return canvas.toDataURL();
    }
    
    export class Marker {
      constructor(map, position, options) {
        this.marker = new Microsoft.Maps.Pushpin(PositionToLocation(position), {
          icon: draw(options.svgIcon, options.fillColor, options.angle),
        });
        map.entities.push(this.marker);
        this.map = map;
        this.options = options;
      }
    
      setOptions(options) {
        this.marker.setOptions({
          icon: draw(this.options.svgIcon, this.options.fillColor, options.rotation),
          title: options.title
        });
      }
    }


    See "Marker.setOptions", when the parameter 'rotation' changes, I have to draw a new svg on a new canvas and set it into the marker. This is too complex and is not what I want. I expect I could write the following code to set the rotation if bing map provided 'rotation|getRotation|setRotation':

    setOptions(options) {
      this.marker.setOptions({
        rotation: options.rotation,
        title: options.title,
      });
    }

    By the way, google map provides 'rotation|getRotation|setRotation' for marker(pushpin);


    Jim King





    • Edited by Jim King 2000 Wednesday, February 12, 2020 1:55 AM fix a typo
    Wednesday, October 16, 2019 1:52 AM
  • Hi I tried to use your code but the img.onload function is not triggering it just skip.
    Tuesday, February 11, 2020 10:06 PM
  • Hi Reynan,

    This posting is from 2016 and is for the V7 version of the control.  Jim stated that what he provided is Psuedo code not running code. Please take a look at the push pin samples at https://www.bing.com/api/maps/sdkrelease/mapcontrol/isdk for more up to date code solutions.

    Sincerely,

    IoTGirl


    Tuesday, February 11, 2020 10:56 PM
    Owner
  • Hi IotGirl,

    Thank you, I already look for the documentation of bing map API but there is no sample on how to rotate pushpin image for example 90 degree. There is an arrow with rotation but I can't apply it on the pinpoint image.

    Wednesday, February 12, 2020 1:06 AM
  • Hi Jim,

    That's what I am referring to but I can't drawimage on it on the ctx. the load does not getting triggered.

    Wednesday, February 12, 2020 2:18 AM
  • You can run(or migrate) the sample directly. If the sample behaves the same as your app, it is probably the reason of the environment(browser is too old, dev tool is too old, etc...).

    Jim King


    Wednesday, February 12, 2020 9:30 AM
  • Is this issue related to the image. I was able to display it yesterday. But it disappear again I did not change anything on my code it is weird.

    "A cookie associated with a cross-site resource at http://bing.com/ was set without the `SameSite` attribute. It has been blocked, as Chrome now only delivers cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032."

    Thursday, February 13, 2020 8:44 AM
  • No. The cookie warning is irrelevant. You can create a simple html file (do not need a server, open the html file directly in Chrome) and run the sample code.

    Jim King


    Thursday, February 13, 2020 10:28 AM
  • FYI: To avoid the Bing.com Cookie warning change to Virtual Earth:

    src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap

    to 

    src='http://SDK.VirtualEarth.Net/api/maps/mapcontrol?callback=GetMap

    Sincerely,

    IoTGirl

    Thursday, February 13, 2020 8:12 PM
    Owner