Skip to content

Instantly share code, notes, and snippets.

@ufologist
Created May 31, 2016 09:37
Show Gist options
  • Select an option

  • Save ufologist/6864d941263c6cdf52294e1e70060704 to your computer and use it in GitHub Desktop.

Select an option

Save ufologist/6864d941263c6cdf52294e1e70060704 to your computer and use it in GitHub Desktop.
html2canvas snapshot invisible DOM in a scrollable div
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>html2canvas snapshot invisible DOM in a scrollable div</title>
<style>
/* 为了在页面上能够更好地观察到 canvas 元素 */
html,
body {
height: 100%;
}
canvas {
border: 1px dotted red;
}
/* 假设要快照的 DOM 元素的样式上有结构依赖 */
#container #snapshotme {
color: red;
}
</style>
</head>
<body>
<h1>html2canvas snapshot invisible DOM in a scrollable div</h1>
<h2>要快照的 DOM 元素在滚动区域的底部</h2>
<div id="container" style="height: 150px; border: 1px dashed #aaa; overflow: auto; position: relative;">
<div id="placeholder" style="height: 2000px;"></div>
<p id="snapshotme"><strong>snapshotme</strong></p>
</div>
<p>
其他情况下都好好的, 为什么单单这种情况就有问题呢?
我猜测滚动区域内的 DOM 元素浏览器是"懒渲染"的, 既然还没有渲染出来, 那么就可以认为和 display:none 是一样的效果.
因此 html2canvas 获取这个 DOM 元素的像素数据时拿到的就会是一片空白了.
</p>
<h3>那么我们如何验证这个猜测呢? 就是要证实视野内可见元素才能快照到像素数据这个观点</h3>
<ul>
<li>
<p>滚动 DIV 元素到一定位置, 才能获取到要快照元素的图形数据 <button onclick="snapshotDirect()">snapshotDirect</button></p>
<p><em>不太灵活, 因为需要调整滚动条的位置</em></p>
</li>
<li>
<p>clone 要快照的元素添加到 body 后再快照 <button onclick="snapshotClone2Body()">snapshotClone2Body</button></p>
<p><em>更改了 DOM 结构, 因此如果要快照的 DOM 元素的样式上有结构依赖, 例如 #container #snapshotme {color: red;} 就会出现快照图片与样式不符的问题</em></p>
</li>
<li>
<p>将快照的元素 absolute 后再快照 <button onclick="snapshotAbsolute()">snapshotAbsolute</button></p>
<p><em>如果滚动页面, 让快照的元素(因为父级已经滚动出了视野范围)在视野以外, 还是会出现快照不到像素数据的问题</em></p>
</li>
<li>
<p>将快照的元素 fixed 后再快照 <button onclick="snapshotFixed()">snapshotFixed</button></p>
<p><em>由于 fixed 确保元素是跟着浏览器窗口的滚动条走的, 因此元素始终会在视野范围内始终可见</em></p>
</li>
</ul>
<div style="height: 100%"></div>
<script src="http://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<script>
// https://github.com/niklasvh/html2canvas/issues/590
var snapshotme = document.getElementById('snapshotme');
function snapshotDirect() {
html2canvas(snapshotme).then(function(canvas) {
document.body.appendChild(canvas);
});
}
function snapshotClone2Body() {
var cloneNode = snapshotme.cloneNode(true);
document.body.appendChild(cloneNode);
html2canvas(cloneNode).then(function(canvas) {
document.body.removeChild(cloneNode);
document.body.appendChild(canvas);
});
}
function snapshotAbsolute() {
var rect = snapshotme.getBoundingClientRect();
snapshotme.style.position = 'absolute';
snapshotme.style.top = '0';
snapshotme.style.width = rect.width + 'px';
html2canvas(snapshotme).then(function(canvas) {
snapshotme.style.position = '';
snapshotme.style.top = '';
snapshotme.style.width = '';
document.body.appendChild(canvas);
});
}
function snapshotFixed() {
var rect = snapshotme.getBoundingClientRect();
snapshotme.style.position = 'fixed';
snapshotme.style.top = '0';
snapshotme.style.width = rect.width + 'px';
html2canvas(snapshotme).then(function(canvas) {
snapshotme.style.position = '';
snapshotme.style.top = '';
snapshotme.style.width = '';
document.body.appendChild(canvas);
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment