在 Firefox 上缩放 canvas 不会影响 SVG 图像

Scaling canvas on Firefox doesn't effect SVG images

Firefox 不支持 SVG 图像的 2D canvas 转换,但支持 PNG 图片。

以下代码片段创建了两个具有 2D 绘图上下文的 HTML canvases。对它们都应用了一个简单的缩放变换,然后在上面绘制了一个 20px 大小的正方形 PNG 图像,在底部绘制了一个相同尺寸的 SVG。

在我的 Chromium (v65.0.3325.162) 上,图像按预期放大。但是,在 Firefox (v58.0.2) 上,底部的 canvas(带有 SVG 的那个)没有缩放,这与带有 PNG 源图像的那个不同。

function createPng(xSize, ySize) {
  var canvas = document.createElement("canvas");
  canvas.width = 20;
  canvas.height = 20;
  var ctx = canvas.getContext("2d")
  ctx.fillStyle = "000000";
  ctx.fillRect(0, 0, xSize, ySize);
  
  var img = new Image()
  prom = new Promise(function(resolve, reject) {
    img.onload = function() {resolve(img)}
    img.onerror = function(err) {reject(err)}
  })
  img.src = canvas.toDataURL("image/png");
  return prom
}

function createSvg() {
  var img = new Image()
  var prom = new Promise(function(resolve, reject) {
    img.onload = function() {resolve(img)}
    img.onerror = function(err) {reject(err)}
  })
  img.src =  "https://cdn.rawgit.com/AttilaVM/4e0987aae8bc37b2067fbde591088758/raw/95dcffd67b37540d739f4bd5f33f6bead625a90f/test.svg"
  return prom
}

var containerPng = document.getElementById("container-png")
var canvasPng = document.createElement("canvas")

canvasPng.width = containerPng.clientWidth;
canvasPng.height = containerPng.clientHeight;

containerPng.appendChild(canvasPng);

var ctxPng = canvasPng.getContext("2d");

createPng(20, 20)
.then(function(img) {
  ctxPng.scale(5, 1); 
  ctxPng.drawImage(img, 0, 0)
})
.catch(function(err) {console.error(err)});

var containerSvg = document.getElementById("container-svg")
var canvasSvg = document.createElement("canvas")

canvasSvg.width = containerSvg.clientWidth;
canvasSvg.height = containerSvg.clientHeight;

containerSvg.appendChild(canvasSvg);
var ctxSvg = canvasSvg.getContext("2d");

createSvg()
.then(function(img) {
  ctxSvg.scale(5, 1); 
  ctxSvg.drawImage(img, 0, 0)
})
.catch(function(err) {console.error(err)});
.container {
  position: relative;
  margin: 15px 0 0 0;
  width: 100%;
  height: 20px;
  background-color: #aaaaaa
}

.container > canvas {
  position: absolute;
  top: 0;
  left: 0;
}
<div id="container-png" class="container"></div>
<div id="container-svg" class="container"></div>

截图

铬:

火狐:

问题:

编写代码以在 HTML canvas 上绘制缩放的 SVG 图像的最佳方法是什么,它在 Firefox 和 Chromium 上给出相同的结果?

这实际上不是错误。在您的原始 svg 中,缺少 preserveAspectRatio 属性。这意味着使用默认值 XMidYMid。如果 svg 的 viewBox 纵横比 与目标 viewPort 的纵横比不匹配(你图片)。要关闭此功能,您需要将 preserveAspectRatio="none" 添加到您的 svg 中。我去了 svg 的来源,添加了 preserveAspectRatio="none" 属性,然后这样做:

var x = "data:image/svg+xml;base64,"+ btoa(ser.serializeToString(document.querySelector("svg")))

上面的ser是一个XMLSerializer实例。这将给我一个我可以使用的数据 url:

"data:image/svg+xml;base64,PHN2ZyB4bWxuczpvc2I9Imh0dHA6Ly93d3cub3BlbnN3YXRjaGJvb2sub3JnL3VyaS8yMDA5L29zYiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI2LjQ1OCAyNi40NTgiIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PGxpbmVhckdyYWRpZW50IG9zYjpwYWludD0iZ3JhZGllbnQiIGlkPSJhIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlMjVlNWUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMxMjkwMzMiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCB5Mj0iMjk1LjQ4MiIgeDI9IjEyLjYxNCIgeTE9IjI3Mi4xNjQiIHgxPSIxMi4xOSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLjExMzQ3IDAgMCAxLjExMzQ3IC0xLjUwMSAtMzIuMTk4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJiIiB4bGluazpocmVmPSIjYSIvPjwvZGVmcz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMCAyNzAuNTQyaDI2LjQ1OFYyOTdIMHoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTI3MC41NDIpIi8+PC9zdmc+"

接下来,我创建了一个 fiddle 并修改了这些:

function createSvg() {
  var img = new Image()
  var prom = new Promise(function(resolve, reject) {
    img.onload = function() {resolve(img)}
    img.onerror = function(err) {reject(err)}
  })
  img.src =  "data:image/svg+xml;base64,PHN2ZyB4bWxuczpvc2I9Imh0dHA6Ly93d3cub3BlbnN3YXRjaGJvb2sub3JnL3VyaS8yMDA5L29zYiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI2LjQ1OCAyNi40NTgiIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PGxpbmVhckdyYWRpZW50IG9zYjpwYWludD0iZ3JhZGllbnQiIGlkPSJhIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlMjVlNWUiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMxMjkwMzMiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCB5Mj0iMjk1LjQ4MiIgeDI9IjEyLjYxNCIgeTE9IjI3Mi4xNjQiIHgxPSIxMi4xOSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxLjExMzQ3IDAgMCAxLjExMzQ3IC0xLjUwMSAtMzIuMTk4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJiIiB4bGluazpocmVmPSIjYSIvPjwvZGVmcz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMCAyNzAuNTQyaDI2LjQ1OFYyOTdIMHoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTI3MC41NDIpIi8+PC9zdmc+";
  return prom
}

在此处查看 fiddle:

https://fiddle.jshell.net/ibowankenobi/4ntq2qLz/1/

似乎它解决了我正在测试的 firefox 浏览器中的问题。