Bing Maps API v8 - pushpin SVG URI image

2020-04-16 06:46发布

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);

1条回答
你好瞎i
2楼-- · 2020-04-16 07:36

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);
查看更多
登录 后发表回答