javascript - 在 Firefox 上缩放 Canvas 不会影响 SVG 图像

标签 javascript firefox cross-browser html5-canvas

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

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

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

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>

屏幕截图

Chrome :

enter image description here

火狐浏览器:

enter image description here

问题:

编写代码在 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实例。这将为我提供一个可以使用的数据网址:

"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 浏览器中的问题。

关于javascript - 在 Firefox 上缩放 Canvas 不会影响 SVG 图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50143933/

相关文章:

javascript - 如何将某些样式应用于 JavaScript 的 "node"对象

javascript - 部分到达视口(viewport)之前的视差效果延迟

javascript - Axios.catch 不捕获网络/控制台错误

javascript - Jest - 在 typescript 中模拟一个命名的类导出

javascript - Firefox 的 forEachFeatureatPixel 速度非常慢

javascript - Base64:如何编码/解码页面的整个 HTML 代码

css - 渐变 - 跨浏览器一致性

javascript - window.getSelection 在textarea中获取正确的选择

css - 背景大小在 Chrome 中无法正常工作

html - Firefox 隐藏没有内容和高度的表格