javascript - JS - canvas.toDataURL 失败

标签 javascript canvas google-maps-api-3

我最近一直在使用一些谷歌地图,我需要旋转 map 标记的图标。我做了一些研究,发现了This Answer .

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

这是代码:

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

旋转图标代码:

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

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

我在 Windows 8.1 上使用 Chrome 48

我注意到还有一些奇怪的事情。如果我将 URL 更改为 /img/logo.png ,它创建了我想要的图像,但尺寸错误。 canvas.toDataURL 输出 this

-编辑-
/img/airplane_icon.png可以查到here
/img/logo.png可以查到here

-编辑2-
所以,我做了一个test page ,并发现它工作......所以我回到我的第一页,并注意到如果我有 <img src="/img/airplane_icon.png">在 map Canvas 之后,页面将工作,但如果我删除它,页面将无法工作。奇怪的。现在我只需添加一个 display:none到 img,但有人知道为什么必须包含 img 才能使页面正常工作吗?

最佳答案

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

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

proof of concept fiddle

代码片段:

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
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map-canvas"></div>

关于javascript - JS - canvas.toDataURL 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35531600/

相关文章:

google-maps - 使用 Google HeatMap 覆盖时,IE8 会抛出长时间运行的脚本错误

javascript - 从 markerclusterer 获取标记信息

javascript - 用于否定父元素中特定 HTML 元素的 JQuery 选择器

javascript - jqGrid - 未显示寻呼机。如何启用它?

javascript - 内联编辑,旁边有图标

java - 从事 Java GUI/Canvas 项目

javascript - 字符串连接在 JS 范围内不起作用

javascript - 在 EaselJS 中将矢量绘制到位图

Android:如何使用 Canvas /绘制位图缩放位图以适合屏幕大小?

Javascript - Google map - 自动填充