JS - canvas.toDataURL失败

时间:2016-02-21 02:27:54

标签: javascript canvas google-maps-api-3

我最近一直在处理一些谷歌地图,我需要旋转地图标记的图标。我做了一些研究,遇到了This Answer

不幸的是,它无法正常工作。它不会渲染我需要的图像。 canvas.toDataURL生成的URL是一个空白图像(大小正确)。

以下是代码:

var o = document.getElementById('opaque');
var p = document.querySelector('.page-container');

o.style.height = window.getComputedStyle(p).getPropertyValue("height");

RotateIcon代码:

var latlong0=new google.maps.LatLng(44.422036688671, -73.857908744819);    function initialize() {
  var mapOptions = {
    center: { lat: 44.422036688671, lng: -73.857908744819},
    zoom: 0
  };
  var map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions);
  var airplane = 'img/airplane_icon.png';

  var infowindow0=new google.maps.InfoWindow({
      content: `
      <div>
        <p class='spectxt'>&lt;Flight #&gt;</p>
    <div style='font-size:10px;'>
          <p class='gentxtl'>Airline: <span class='acptxt'>Aero Test Ltd</span></p>
      <p class='gentxtl'>Aircraft: <span class='acptxt'>Boeing 717-200 HGW</span></p>
      <p class='gentxtl'>From: <span class='acptxt'>YYZ</span></p>
      <p class='gentxtl'>To: <span class='acptxt'>YHZ</span></p>
        </div>
      </div>
      `
    });

  var mark0=new google.maps.Marker({
    position: latlong0,
    map: map,
    title:'Aircraft',
    icon: {
            url: RotateIcon
                .makeIcon(
                    '/img/airplane_icon.png')
                .setRotation({deg: 78})
                .getUrl()
        }
  });
  mark0.setMap(map);mark0.addListener('click', function() {
      infowindow0.open(map, mark0);
    });    }
google.maps.event.addDomListener(window, 'load', initialize);

图像与网页位于同一个域中,两个资源都是常规http(无https)。 Chrome DevTools不会报告任何警告或错误。 canvas.toDataURL输出this

我在Windows 8.1上使用Chrome 48

我注意到其他一些奇怪的东西。如果我将网址更改为 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 || 50; this.options.height = this.options.height || this.rImg.height || 50; 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'); }; ,则会创建我想要的图片,但尺寸错误。 canvas.toDataURL输出this

CNC中
可以找到/img/logo.png here 可以找到/img/airplane_icon.png

/img/logo.png

-EDIT 2-
所以,我做了一个here,发现它正常工作......所以我回到了我的第一页,注意到如果我在地图画布后面有<img src="/img/airplane_icon.png">,页面就可以了,但是如果我删除它,页面将不会。奇怪。现在我只是要向img添加一个display:none,但有没有人知道为什么必须包含img才能让页面正常工作?

1 个答案:

答案 0 :(得分:0)

如果图像的异步加载存在问题,如果它尚未在缓存中可用,则看起来像是一个问题。解决这个问题的一个选择是将图标作为数据URI加载:

void trunc(const std::string& str, std::vector<std::string>& vec)
{
    std::string buf; 
    std::stringstream ss(str); 

    ss >> buf;
    vec.push_back(buf);

    while (ss >> buf)
    {        
        if(vec.back().length() + buf.length() < 64)            
            vec.back() += ' ' + buf;            
        else        
            vec.push_back(buf);

    }
}


 int main()
{
    std::vector<std::string> vec;
    std::string text("AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAA AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAA");

     trunc(text, vec);

     for(auto itr : vec)
     {
         std::cout << itr << std::endl;
     }
     return 1;

 }

proof of concept fiddle

代码段

var airplaneIcon = new RotateIcon({
  url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAAlQTFRF////AH8OAH8OqhPhTgAAAAJ0Uk5TADqwnxSKAAAAZ0lEQVQoz2NgoCJQQOYwrkTmMa0aijy2VQ5IvKxVS5ClViFJZgF5S5ClEJJZYN4SZCmYpBaUtwDGm7RKCsGbAHSLFIw3AewyqQUD5XepVRNwhQTjqlUrcYULF5DXgOAtYchqoF5yAwBuvj9B9E9ozgAAAABJRU5ErkJggg==',
  height: 50,
  width: 50
})
var mark0 = new google.maps.Marker({
  position: latlong0,
  map: map,
  title: 'Aircraft',
  icon: {
  // size: new google.maps.Size(128, 128),
    scaledSize: new google.maps.Size(20, 20),
    anchor: new google.maps.Point(10, 10),
    url: airplaneIcon.setRotation({
        deg: 78
    })
    .getUrl()
  }
});
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 || 50;
  this.options.height = this.options.height || this.rImg.height || 50;
  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');
};

var map;
var latlong0 = new google.maps.LatLng(44.422036688671, -73.857908744819);

function initialize() {
  var mapOptions = {
    center: {
      lat: 44.422036688671,
      lng: -73.857908744819
    },
    zoom: 5
  };
  map = new google.maps.Map(document.getElementById('map-canvas'),
    mapOptions);
  var airplane = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAAlQTFRF////AH8OAH8OqhPhTgAAAAJ0Uk5TADqwnxSKAAAAZ0lEQVQoz2NgoCJQQOYwrkTmMa0aijy2VQ5IvKxVS5ClViFJZgF5S5ClEJJZYN4SZCmYpBaUtwDGm7RKCsGbAHSLFIw3AewyqQUD5XepVRNwhQTjqlUrcYULF5DXgOAtYchqoF5yAwBuvj9B9E9ozgAAAABJRU5ErkJggg==';

  var infowindow0 = new google.maps.InfoWindow({
    content: `
      <div>
        <p class='spectxt'>&lt;Flight #&gt;</p>
    <div style='font-size:10px;'>
          <p class='gentxtl'>Airline: <span class='acptxt'>Aero Test Ltd</span></p>
      <p class='gentxtl'>Aircraft: <span class='acptxt'>Boeing 717-200 HGW</span></p>
      <p class='gentxtl'>From: <span class='acptxt'>YYZ</span></p>
      <p class='gentxtl'>To: <span class='acptxt'>YHZ</span></p>
        </div>
      </div>
      `
  });
  var airplaneIcon = new RotateIcon({
    url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAAAlQTFRF////AH8OAH8OqhPhTgAAAAJ0Uk5TADqwnxSKAAAAZ0lEQVQoz2NgoCJQQOYwrkTmMa0aijy2VQ5IvKxVS5ClViFJZgF5S5ClEJJZYN4SZCmYpBaUtwDGm7RKCsGbAHSLFIw3AewyqQUD5XepVRNwhQTjqlUrcYULF5DXgOAtYchqoF5yAwBuvj9B9E9ozgAAAABJRU5ErkJggg==',
    height: 50,
    width: 50
  })
  var mark0 = new google.maps.Marker({
    position: latlong0,
    map: map,
    title: 'Aircraft',
    icon: {
      // size: new google.maps.Size(128, 128),
      scaledSize: new google.maps.Size(20, 20),
      anchor: new google.maps.Point(10, 10),
      url: airplaneIcon.setRotation({
          deg: 78
        })
        .getUrl()
    }
  });
  mark0.setMap(map);
  mark0.addListener('click', function() {
    infowindow0.open(map, mark0);
  });
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}