Создание правильного захвата изображения текущего экрана с использованием jquery или PHP или конвертировать div в pdf

Я пишу код для преобразования svg в inline svg и скриншот этого div. Пожалуйста, проверьте. Пожалуйста, скопируйте этот код int на свой локальный хост и протестируйте его. Потому что экранный снимок отличается разной шириной.

https://jsfiddle.net/7bqukhff/15/

<link href="style.css" rel="stylesheet"> <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"> <div id="test"> <div class="description-div"> <p>Sample description</p> </div> <div class="img-div" id="img-div"></div> </div> <form class="cf"> <div class="half left cf"> <input type="text" name="user-name" required> <select name="design-name" class="desgign-class" required> <option value="" >select</option> <option>2</option> <option>3</option> <option>4</option> </select> <input type="submit" name="submit" value="submit" class="submit"> </div> </form> </div> <div class="new"> <a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a> </div> <script> $(function() { $(".desgign-class").on("change",function(){ var op=$(this).val(); if(op!=0){ $('.btn').show(); $('.img-div').html(''); if(op==2){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='https://istack.000webhostapp.com/1tf.svg'>"); } } if(op==3){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='https://istack.000webhostapp.com/_1tf.svg'>"); } } if(op==4){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='http://svgur.com//i/1yP.svg'>"); } } } else{ $('.btn').hide(); } $('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('img-div'); 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); }); </script> html, body { background: #f1f1f1; font-family: 'Merriweather', sans-serif; padding: 1em; } form { border: 2px solid blue; float: left; max-width: 300px; padding: 5px; text-align: center; width: 30%; } .img-div { border: 1px solid black; display: block; float: left; margin-right: 86px; overflow: hidden; width: 50%; padding: 10px; } .btn { display: none; overflow: hidden; width: 100%; } .new{ display: block; overflow: hidden; width: 100%; } .description-div { border: 2px solid green; float: left; margin-right: 32px; padding: 3px; width: 13%; } .submit { background: wheat none repeat scroll 0 0; border: 1px solid red; cursor: pointer; } 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)); } } 

Но здесь (1), когда я снимаю снимок экрана img-div скриншот отличается от исходного. Почему это происходит?

(2) Также в скриншоте 4-го варианта svg не появляется. На самом деле у меня слишком много вариантов и слишком много изображений. Теперь я пишу только 3 варианта.

(3) Можно ли сохранить этот снимок экрана на сервер [конкретную папку], когда пользователь отправляет форму?

(4) Есть ли какой-либо другой метод без использования html-холста?

(5) КАК КАК ВЫКЛЮЧАЕТ ЭКРАНИРОВАНИЕ ЭКРАНА В КОМПЬЮТЕРНЫХ РАБОТАХ? или расширение браузера, например https://chrome.google.com/webstore/detail/awesome-screenshot-screen/nlipoenfbbikpbjkfpfillcgkoblgpmj?hl=ru .

Краткая форма: у меня есть веб-сайт. В котором пользователь может выбрать любой svg из данного списка svg. Когда пользователь выбирает один svg, тогда svg преобразуется в строку svg, отображаемую в одном div. Также пользователь может переместить этот svg на любую часть div. После всего этого пользователь заполнит форму и отправит. Во время отправки мы хотим загрузить снимок экрана этого div, тогда мы понимаем, что пользователь выбирает, какой цвет, где находится svg imge и т. Д.

Пожалуйста, проверьте ниже упомянутое решение. Я просто попытался скрыть вашу проблему.

 $(function() { $(".desgign-class").on("change",function(){ var op=$(this).val(); if(op!=0){ $('.btn').show(); $('.img-div').html(''); if(op==2){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='https://istack.000webhostapp.com/1tf.svg'>"); } } if(op==3){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='https://istack.000webhostapp.com/_1tf.svg'>"); } } if(op==4){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='http://svgur.com//i/1yP.svg'>"); } } } else{ $('.btn').hide(); } $('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('img-div'); 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'); var sleft = 0; svgs.forEach(function(svg) { var svgWidth = svg.width.baseVal.value; var svgHeight = svg.height.baseVal.value; var svgLeft = 10; var svgTop = getOffset(svg).top - 40; 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); }); . $(function() { $(".desgign-class").on("change",function(){ var op=$(this).val(); if(op!=0){ $('.btn').show(); $('.img-div').html(''); if(op==2){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='https://istack.000webhostapp.com/1tf.svg'>"); } } if(op==3){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='https://istack.000webhostapp.com/_1tf.svg'>"); } } if(op==4){ for(var i = 0;i<op;i++){ $('.img-div').append("<img src='http://svgur.com//i/1yP.svg'>"); } } } else{ $('.btn').hide(); } $('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('img-div'); 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'); var sleft = 0; svgs.forEach(function(svg) { var svgWidth = svg.width.baseVal.value; var svgHeight = svg.height.baseVal.value; var svgLeft = 10; var svgTop = getOffset(svg).top - 40; 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; float: left; max-width: 300px; padding: 5px; text-align: center; width: 30%; } .img-div { border: 1px solid black; display: block; float: left; margin-right: 86px; overflow: hidden; width: 50%; padding: 10px; } .btn { display: none; overflow: hidden; width: 100%; } .new{ display: block; overflow: hidden; width: 100%; } .description-div { border: 2px solid green; float: left; margin-right: 32px; padding: 3px; width: 13%; } .submit { background: wheat none repeat scroll 0 0; border: 1px solid red; cursor: pointer; } 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; } @media print { html, body { padding:0 !important;margin:0 !important; } } тем @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; float: left; max-width: 300px; padding: 5px; text-align: center; width: 30%; } .img-div { border: 1px solid black; display: block; float: left; margin-right: 86px; overflow: hidden; width: 50%; padding: 10px; } .btn { display: none; overflow: hidden; width: 100%; } .new{ display: block; overflow: hidden; width: 100%; } .description-div { border: 2px solid green; float: left; margin-right: 32px; padding: 3px; width: 13%; } .submit { background: wheat none repeat scroll 0 0; border: 1px solid red; cursor: pointer; } 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; } @media print { html, body { padding:0 !important;margin:0 !important; } } 
 <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"> <div id="test"> <div class="description-div"> <p>Sample description</p> </div> <div class="img-div" id="img-div"></div> </div> <form class="cf"> <div class="half left cf"> <input type="text" name="user-name" required> <select name="design-name" class="desgign-class" required> <option value="" >select</option> <option>2</option> <option>3</option> <option>4</option> </select> <input type="submit" name="submit" value="submit" class="submit"> </div> </form> </div> <div class="new"> <a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a> </div> 

Насколько я могу судить, это рабочая версия: https://jsfiddle.net/7bqukhff/16/

Разница исходит из того, как вы рисуете на offscreenCanvas .

Вот что происходит в вашем коде:

  1. Вы устанавливаете размеры offscreenCanvas на ширину и высоту SVG (вместо ширины и высоты обертки) в строках 108 и 109
  2. Вы вычитаете что-то (40 и 62) из ​​левой и верхней позиции SVG. Эта позиция относится к позиции на странице, а не к относительной позиции SVG в оболочке.
  3. Вы рисуете SVG на холсте с координатами страницы вместо относительных координат

Исправление выглядит так:

Сначала установите размеры холста в размеры обертки:

 var wrapperRect = wrapper.getBoundingClientRect() // ... offScreenCanvas.width = wrapperRect.width; offScreenCanvas.height = wrapperRect.height; 

Затем нарисуйте svg, используя относительные координаты:

 var svgLeft = getOffset(svg).left - wrapper.left; var svgTop = getOffset(svg).top - wrapper.top; 

Кажется, это работает так, как вам нужно.

PS: Опция «4» не работает, но это связано с использованием HTTP на HTTPS-сайте, поэтому она не загружается из-за ограничений безопасности.