捕获包含内联svg的div并将其下载为图像
我写了代码来捕获使用html5的页面截图。一切都很好,除非页面包含一个svg。当我将svg转换为内联svg之后,截图不会捕获内联svg。
I wrote code to capture a screenshot of a page using html5. Everything is fine except when the page contains an svg. When I convert svg to inline svg after that screenshot is not capturing the inline svg.
请检查 https://jsfiddle.net/7bqukhff/4/
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
<script src="https://github.com/niklasvh/html2canvas/releases/download/0.5.0-alpha1/html2canvas.svg.js"></script>
<script src="https://github.com/niklasvh/html2canvas/releases/download/0.5.0-alpha1/html2canvas.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="wrapper">
<h1>Scrrenshot</h1>
<div class="img-div"><img src='https://istack.000webhostapp.com/1tf.svg'></div>
<form class="cf">
<div class="half left cf">
<input type="text" id="input-name" placeholder="Name">
<input type="email" id="input-email" placeholder="Email address">
<input type="text" id="input-subject" placeholder="Subject">
</div>
<div class="half right cf">
<textarea name="message" type="text" id="input-message" placeholder="Message"></textarea>
</div>
<input type="submit" value="Submit" id="input-submit">
</form>
</div>
<a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a>
$(function() {
$('img').each(function() {
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if (typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass + ' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
});
(function(exports) {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype || nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function(el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function screenshotPage() {
var wrapper = document.getElementById('wrapper');
html2canvas(wrapper, {
onrendered: function(canvas) {
canvas.toBlob(function(blob) {
saveAs(blob, 'myScreenshot.png');
});
}
});
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function(e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function generate() {
screenshotPage();
}
exports.screenshotPage = screenshotPage;
exports.generate = generate;
})(window);
对于这个特殊的svg没有问题,但是对于某些svg,捕获的图像与原始
For this particular svg there is no problem, but for some svg the captured image is different from the original.
有没有任何方法来捕获截图而不使用html画布?如果不是我如何更改我的代码以正确捕获svg元素?
Is there any method for capturing a screenshot without using html canvas? If not how can I change my code to capture svg elements correctly?
我认为现在每个人都熟悉可怕的屏幕截图扩展 https://www.awesomescreenshot.com/ 。他们是如何进行此屏幕捕获的?
I think now everyone is familiar with awesome screen shot extension https://www.awesomescreenshot.com/. How are they doing this screen capture?
Angular 1(不是2或更高版本),React JS,Vue.js,Aurelia js或任何现代JavaScript您可以使用一个名为
Is there any method in Angular 1 (not 2 or above), React JS , Vue.js, Aurelia js or any modern JavaScript library for taking a screenshot?
.com / canvg / canvgrel =nofollow noreferrer> canvg (用于在画布上正确渲染SVG),以及 html2canvas 。
You can achieve this using a JavaScript library called canvg ( for rendering SVG on canvas properly ) , along with html2canvas .
ᴡᴏʀᴋɪɴɢᴇxᴀᴍᴘʟᴇ
$(function() {
$('img').each(function() {
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if (typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass + ' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
});
(function(exports) {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype || nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function(el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function screenshotPage() {
var wrapper = document.getElementById('wrapper');
html2canvas(wrapper, {
onrendered: function(canvas) {
function getOffset(el) {
el = el.getBoundingClientRect();
return {
left: el.left + window.scrollX,
top: el.top + window.scrollY
}
}
var cachedCanvas = canvas;
var ctx = canvas.getContext('2d');
var svgs = document.querySelectorAll('svg');
svgs.forEach(function(svg) {
var svgWidth = svg.width.baseVal.value;
var svgHeight = svg.height.baseVal.value;
var svgLeft = getOffset(svg).left - 40;
var svgTop = getOffset(svg).top - 62;
var offScreenCanvas = document.createElement('canvas');
offScreenCanvas.width = svgWidth;
offScreenCanvas.height = svgHeight;
canvg(offScreenCanvas, svg.outerHTML);
ctx.drawImage(cachedCanvas, 0, 0);
ctx.drawImage(offScreenCanvas, svgLeft, svgTop);
});
canvas.toBlob(function(blob) {
saveAs(blob, 'myScreenshot.png');
});
}
});
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function(e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function generate() {
screenshotPage();
}
exports.screenshotPage = screenshotPage;
exports.generate = generate;
})(window);
@import url(https://fonts.googleapis.com/css?family=Merriweather);
$red: #e74c3c;
*,
*:before,
*:after {
@include box-sizing(border-box);
}
html,
body {
background: #f1f1f1;
font-family: 'Merriweather', sans-serif;
padding: 1em;
}
h1 {
text-align: center;
color: #a8a8a8;
@include text-shadow(1px 1px 0 rgba(white, 1));
}
form {
border: 2px solid blue;
margin: 20px auto;
max-width: 600px;
padding: 5px;
text-align: center;
}
input,
textarea {
border: 0;
outline: 0;
padding: 1em;
@include border-radius(8px);
display: block;
width: 100%;
margin-top: 1em;
font-family: 'Merriweather', sans-serif;
@include box-shadow(0 1px 1px rgba(black, 0.1));
resize: none;
&:focus {
@include box-shadow(0 0px 2px rgba($red, 1)!important);
}
}
#input-submit {
color: white;
background: $red;
cursor: pointer;
&:hover {
@include box-shadow(0 1px 1px 1px rgba(#aaa, 0.6));
}
}
textarea {
height: 126px;
}
}
.half {
float: left;
width: 48%;
margin-bottom: 1em;
}
.right {
width: 50%;
}
.left {
margin-right: 2%;
}
@media (max-width: 480px) {
.half {
width: 100%;
float: none;
margin-bottom: 0;
}
}
/* Clearfix */
.cf:before,
.cf:after {
content: " ";
/* 1 */
display: table;
/* 2 */
}
.cf:after {
clear: both;
}
.half.left.cf > input {
margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
<script src="https://cdn.rawgit.com/canvg/canvg/master/canvg.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<h1>Scrrenshot</h1>
<div class="img-div">
<img src='https://istack.000webhostapp.com/1tf.svg'>
</div>
<form class="cf">
<div class="half left cf">
<input type="text" id="input-name" placeholder="Name">
<input type="email" id="input-email" placeholder="Email address">
<input type="text" id="input-subject" placeholder="Subject">
</div>
<div class="half right cf">
<textarea name="message" type="text" id="input-message" placeholder="Message"></textarea>
</div>
<input type="submit" value="Submit" id="input-submit">
</form>
</div>
<a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a>