yincrash
yincrash

Reputation: 6484

Is it possible to use several images as the Google Maps v3 MarkerImage?

I want a map marker composed of three images. Two images will be the same across all markers where one is variable. There doesn't seem to be a way to specify multiple images on the MarkerImage class. The only way that I can think of is to draw all the images to a canvas then outputting it as a png dataURL for the MarkerImage class. That seems like overkill though.

Upvotes: 6

Views: 4935

Answers (4)

Misha Beskin
Misha Beskin

Reputation: 325

Yes, you can use multiple images and set them as one image for each Marker Icon in your array of the map markers.

What's more important is that you can use images that are on a remote server. For example, in my case, I loaded an array of sites that each has an image for the site, so I'm merging an image of a marker with the image of the site (received from server). Here is my solution:

mergeImages(element) {

    var canvas: HTMLCanvasElement = this.canvas.nativeElement;

    var context = canvas.getContext('2d');

    let img1 = new Image();
    let img2 = new Image();

    img1.onload = function () {
      canvas.width = img1.width;
      canvas.height = img1.height;
      img2.crossOrigin = 'anonymous';
      img2.src = element.info.image || './assets/img/markers/markerIcon42.png';
    };
    img2.onload = () => {

      context.clearRect(0, 0, canvas.width, canvas.height);
      context.globalAlpha = 1.0;
      context.drawImage(img1, 0, 0);
      context.globalAlpha = 1; //Remove if pngs have alpha
      context.globalCompositeOperation = 'destination-over';
      if (element.info.image === null) {
        context.drawImage(img2, 11, 4, 42, 42);
      } else {
        context.drawImage(img2, 15, 7, 35, 35);
      }
      var dataURL = canvas.toDataURL('image/png', 1.0);
      console.log(dataURL);
      this.markers.push({
        lat: element.info.location.latitude,
        lng: element.info.location.longitude,
        controllerInfo: element.info,
        icon: {
          url: dataURL,
          labelOrigin: { x: 32, y: -10 },
          scaledSize: {
            width: 64,
            height: 64
          },
          origin: { x: 0, y: 0 },
          anchoriconAnchor: { x: 7, y: 7 },
        },
        controllerStaus: element.status,
        label: {
          text: element.info.siteName,
          color: "#ED2C2C",
          fontWeight: "500",
          fontSize: "14px"
        }

      });
      console.log(this.markers);
    };
    img1.src = './assets/img/markers/map-marker64.png';

  }

One Important thing to add is "img2.crossOrigin = 'anonymous';" this will prevent toDataUrl cors-orign error.

This solution is good also for clustering

I hope it will help

Upvotes: 1

Bogdan D
Bogdan D

Reputation: 5631

You can use an excellent small library, RichMarker. Its documentation is here.

You can even inherit it and create a custom marker class, something like this:

Ns.Marker = function(properties) {

    RichMarker.call(this, properties);

    this.setContent('<div class="three-images-marker">' +
            properties.NsImage1 ? '<div class="marker-image-1"><img src="'+properties.NsImage1+'"/></div>' : '' + 
            properties.NsImage2 ? '<div class="marker-image-2"><img src="'+properties.NsImage2+'"/></div>' : '' +
            properties.NsImage3 ? '<div class="marker-image-3"><img src="'+properties.NsImage3+'"/></div>'+ 
        '</div>');
};

Ns.Marker.prototype = Object.create(RichMarker.prototype);

And then use it like this:

var gorgeousMarker = new Ns.Marker({
      position: yourMarkerLatlng,
      map: yourMap,
      NsImage1: 'example.com/image1.png',
      NsImage2: 'example.com/image2.png',
      NsImage3: 'example.com/image3.png',
});

'Ns' is whatever namespace you use, if you do.

From here on it's CSS work, you can position the images as you like.

Upvotes: 0

Tomas
Tomas

Reputation: 59585

I would try to define a new class which would inherit from google.maps.MarkerImage that would allow it and then just call marker.setIcon() with this object.

Also have a look here and here.

Upvotes: 1

Bryan Weaver
Bryan Weaver

Reputation: 4473

I don't think it is possible with three separate images.

If two of the images are always the same I guess you could combine them into one and store it in the icon property and then use the variable image in the shadow property or vise versa (the icon will always be on top of the shadow). You just need to manipulate the size and position of the MarkerImage objects.

working example: http://jsfiddle.net/mG4uz/1/

var image1 = new google.maps.MarkerImage(
   'http://google-maps-icons.googlecode.com/files/sailboat-tourism.png',
    new google.maps.Size(45, 90), //adjust size of image placeholder  
    new google.maps.Point(0, 0), //origin
     new google.maps.Point(0, 25) //anchor point
  );

var image2 = new google.maps.MarkerImage(
   'http://google-maps-icons.googlecode.com/files/sailboat-tourism.png',
   new google.maps.Size(45, 45),
   new google.maps.Point(0, 0), 
   new google.maps.Point(0, 0) 
  );

var marker = new google.maps.Marker({
   position: centerPosition,
   map: map,
   icon: image1,
   shadow:image2
  });

Upvotes: 9

Related Questions