简体   繁体   中英

Bing Maps API v8 - pushpin SVG URI image

I'm trying to build a custom bing maps v8 API pushpin combining text and a small uri data image, but I get an 'Uncaught InvalidStateError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.' error on the browser console. Any ideas?

MapOptions = { credentials: 'mycredentials', mapTypeId: Microsoft.Maps.MapTypeId.road, zoom: 10, showMapTypeSelector: true, enableInertia: false, enableClickableLogo: false, disableKeyboardInput: true, navigationBarMode: navigationBarMode.minified, showLocateMeButton: true };

map = new Microsoft.Maps.Map(document.getElementById("MapDIV"), MapOptions);

LayerShapes = new Microsoft.Maps.Layer();
LayerShapes.setZIndex(101);

map.layers.insert(LayerShapes);

var svgTemplate = '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"> <p>TEXT</p> {htmlContent} </div></foreignObject></svg>';
var customHtml = ' <image width="32" height="32" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAcCAYAAACUJBTQAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wQbECUudScMXAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAACGUlEQVRIx+3Wy2sTURTH8e/NTDIzaZMxadMWhyBUSheiiyo+QPpHuHIhdOfSP8GlbkXEhTv/gNau3LgRurEIUqlWU2ubh7evPEg6NjOZJHNdlIgLo11YRcj5A84Hfpx7zxFKKcUJlw7gOM6JAVLKIwTg4avbfxy4c/UJABH+Qg2QAfKfI98f48vc/CCuATJA/iEilFKq3/q98XTk2I0W5qp916/41SHhOM6xoIW5KlLK/t/K6oNbwlAdknELYSZpxTMkxrO4XoCUUv0O6gHlYkjHWxF+yyWTsKit57CGbbTMGSJWepTh05PIRof3mxLNjNP0Pdp+i9ziIyGl7BtFD1hdOqRdei5ijW2shkSvS8LAJTM2gh4JiWzvFNksFdAsA3s0Ram4TrtZJxnXCLwKWSF+CvWAt89czmffiEQ0gGYZzSuTX3tNx60Q1Pcxwyb67JUL7Jb38VsdojETz2ux8W6JqG6iJaOoGLTr98WP0fWAsZgQ849v8mnZYeriLNinwAup722RsW12cysYiRT62voGwymbbsQgMZREcMD1yzN4nkctrNEV4HbrTKeFKNeOJlFKiXtwV2ganJvKkF8rsvxiEd8P0FSTiXQa2wxJxEz2yl/QA2Mc2Qihq7NdqdE5rJAc2ufsZBbTiIIGXWXTVeCIa0glMQwh8vl7hMDHD5+Zmb7E16ZPtVrFilnsFLY42CngTDhEohbfALpF/s+4JwbyAAAAAElFTkSuQmCC"/> ';

var PinPos = new Microsoft.Maps.Location(Lat, Lng);
pin = new Microsoft.Maps.Pushpin(PinPos, { icon: svgTemplate.replace('{htmlContent}', customHtml), width: 32});

LayerShapes.add(pin);

I came across the same issue. It happens because it tries to draw pushpin icons with unloaded images.

The general idea is to preload images in JS code before using it in pushpin icons.

I solved it by this way:

  1. I preload images to array
  2. I used canvas instead of 'svg'
var imageArray = [];
var imagesFiles = ['home_16.png', 'home_16_done.png', 'not existing.png'];

    function preLoadImages(callback) {

        var filesCount = imagesFiles.length;
        for (var i = 0; i < imagesFiles.length; i++) {
           var imageObj = new Image();
           imageObj.src = '/images/' + imagesFiles[i];
           imageObj.name = imagesFiles[i];
           imageObj.onload = (function (img) {
            imageArray.push({ name: img.target.name, object: img.target });

            filesCount--;

            if (filesCount === 0) {
               if (callback)
                    callback(imageArray);
            }});

           imageObj.onerror = function () { //even image is not loaded

              filesCount--;
              if (filesCount === 0) {
                 if (callback)
                     callback(imageArray);
               }};
            }
     }


         ....

        pushpin = new Microsoft.Maps.Pushpin(location,
        { icon: createCanvasContent(imageArray[i], parameters[])
        .....

        function createCanvasContent(img, parameters){

          var c = document.createElement('canvas');
          c.width = img.width + 2;
          c.height = img.height + 2;

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

          context.fillStyle = bgrcolor;
          context.fillRect(0, 0, 18, 18);
          c.style.opacity = '0.8';
          //Draw image
          context.drawImage(img, 1, 0, c.width - 2, c.height - 2);

          return c.toDataURL();
        }

You can use all features from canvas tag like

context.textAlign = "center";
context.strokeText(text, x, y);
context.fillStyle = 'white';
context.fillText(text, x, y);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM