我正在尝试拍摄现有元素的图像。首先,我将图像复制到SVG元素中的foreignObject,然后序列化它并将其用作“数据”图像源。但由于某种原因,在Chrome中,我看到元素呈现的方式有点不同。有没有人知道为什么会这样,以及可以做些什么来纠正它?
我的HTML是这样的:
<!DOCTYPE html>
<html>
<head>
<style>
html,
body {
margin: 0
}
.x {
border: 1px solid black;
float: left;
width: 100.3px;
}
</style>
<script>
function test() {
let x = document.getElementById('xx')
let i = document.getElementById('if')
i.contentDocument.body.appendChild(document.getElementById('sv').cloneNode(true))
let c = i.contentDocument
let s = c.getElementById('sv')
let t = c.getElementById('st')
let f = c.getElementById('fo')
i.width = x.offsetWidth * 2
i.height = x.offsetHeight
s.viewBox.baseVal.width = x.offsetWidth
s.viewBox.baseVal.height = x.offsetHeight
s.width.baseVal.value = x.offsetWidth
s.height.baseVal.value = x.offsetHeight
f.width.baseVal.value = x.offsetWidth
f.height.baseVal.value = x.offsetHeight
t.textContent = document.getElementsByTagName('STYLE')[0].textContent
f.appendChild(x.cloneNode(true))
d = new XMLSerializer().serializeToString(s)
g = c.createElement('IMG')
g.width = x.offsetWidth
g.height = x.offsetHeight
g.src = 'data:image/svg+xml,' + encodeURIComponent(d)
c.body.appendChild(g)
}
</script>
</head>
<body onclick="test()">
<div class="x" id="xx">
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul>
</div>
<svg xmlns="http://www.w3.org/2000/svg" id="sv" viewBox="0 0 100 100" width="100px" height="100px">
<style id="st"></style>
<foreignObject id="fo" width="100px" height="100px" style="background:lightgray"></foreignObject>
</svg>
<iframe id="if"></iframe>
</body>
</html>
以下是结果(点击body中的某个位置后):
左边的列表是原始的,然后是我用于SVG的蓝图,然后是包含两个元素的iframe:一个是SVG元素,内部有一个foreignObject,显示相同的列表,另一个是IMG元素,它具有相同的SVG,序列化,作为其源。由于某种原因,它们在Chrome中的呈现方式略有不同(在Firefox中没有问题)。
1条答案
按热度按时间bz4sfanl1#
好吧,看来确实有一个变通办法。它会在Safari中造成混乱,因此,我没有很好的跨平台代码,但问题是HTML的呈现方式会因
window.devicePixelRatio
而有所不同。对于图像,它始终为1。但对于主要内容,它是2(视网膜显示)。解决方法是首先复制SVG中的内容,就像这里一样,但是用
zoom = 1/devicePixelRatio
将SVG Package 在DIV中;然后根据克隆内容的实际offsetHeight
和offsetWidth
调整所有维度,然后才执行XML序列化和其他操作。