Недавно я использовал html2canvas.js при написании проектов, которые могут реализовать функцию скриншота страницы, но столкнулся со многими подводными камнями, поэтому напишу эссе, чтобы их записать.
При использовании html2canvas вы можете столкнуться с такими проблемами, как возможность захвата только визуального интерфейса, снимок экрана не имеет цвета фона и невозможно захватить тег svg. Ниже приводится подробное объяснение.
1. Импортируйте html2canvas.js.Излишне говорить, что это можно получить на github: https://github.com/niklasvh/html2canvas.
Вы также можете импортировать ссылку напрямую: <script src=https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js></script>
Его также очень просто использовать. Вы можете найти соответствующий API в Интернете и просто использовать image/png для создания изображений в формате PNG.
Среди них $(#xxx) — это div, который вы хотите перехватить. Его, конечно, можно получить и через document.
html2canvas($(#xxx), { onrendered: function (canvas) { var url = Canvas.toDataURL(image/png); window.location.href = url; } });
Для других типов изображений, таких как jpg, image/jpeg и т. д., вы можете запросить API самостоятельно.
На этом простой скриншот завершен. Если интерфейс немного сложнее, могут возникнуть различные подводные камни. Давайте разберем их один за другим.
2. Проблема в том, что SVG невозможно перехватить.Когда мы перехватываем div, если в нем есть тег svg, его невозможно перехватить при обычных обстоятельствах. Например, если мы перехватываем блок-схему, мы получим что-то вроде этого:
Видно, что строки блок-схемы не перехватываются, то есть SVG не перехватывается. Решение на данный момент состоит в том, чтобы преобразовать SVG в холст, а затем сделать снимок экрана и напрямую загрузить код.
Каждый цикл здесь предназначен для перебора всех тегов svg и преобразования их всех в холст.
if (typeof html2canvas !== 'undefined') { // Ниже представлена обработка svg var nodesToRecover = []; var nodesToRemove = []; var svgElem = cloneDom.find('svg') (индекс, узел) {вар родительский узел = node.parentNode вар svg = node.outerHTML.trim(); var Canvas = document.createElement('canvas'); Canvas.width = 650; Canvas.height = 798; canvg(canvas, svg); if (node.style.position) { Canvas.style.position += node.style; .position; Canvas.style.left += node.style.left; Canvas.style.top += node.style.top; } nodesToRecover.push({ родитель: родительский узел, дочерний элемент: узел }); родительский узел.removeChild(узел); узлыToRemove.push({родительский узел: родительский узел, дочерний элемент: холст }); родительский узел.appendChild(холст });
Здесь необходим Canvg.js и его файл зависимостей rgbcolor.js. Их можно скачать напрямую из Интернета или напрямую импортировать.
3. Проблема прозрачности фонаНа самом деле это очень просто, поскольку по умолчанию он прозрачный. В html2canvas есть параметр background для добавления цвета фона, как показано ниже:
html2canvas(cloneDom, { onrendered: function(canvas) { var url =canvas.toDataURL(image/png); }, background:#fafafa});4. Проблема возможности запечатлеть только видимую часть
Если элемент div, который необходимо перехватить, выходит за пределы интерфейса, вы можете столкнуться с проблемой неполного перехвата. Как показано на рисунке выше, здесь находится только половина содержимого. Это связано с тем, что невидимая часть скрыта, и html2canvas не может перехватить. скрытый ДОМ.
Поэтому решение на данный момент состоит в том, чтобы использовать клонирование, поместить копию части, которую необходимо перехватить, внизу страницы, а затем использовать html2canvas для перехвата всего элемента div. После завершения перехвата удалите эту часть. Содержание Полный код выглядит следующим образом:
function showQRCode() { ScrollTo(0, 0); //Клонируем узел, значение по умолчанию — false, то есть атрибуты метода не копируются, а true — все копии. var cloneDom = $(#d1).clone(true); //Устанавливаем атрибут z-index клонируемого узла, если он ниже, чем у клонируемого узла. cloneDom.css({ цвет фона: #fafafa, позиция: абсолютная, верх: 0 пикселей, z-индекс: -1, высота: 798, ширина: 650 }); if (typeof html2canvas !== 'undefined') { / /Ниже приведена обработка svg var nodesToRecover = []; var nodesToRemove = []; cloneDom.find('svg');//divReport — это идентификатор dom, который нужно перехватить в картинку svgElem.each(function (index, node) { var родительскийNode = node.parentNode; var svg = node.outerHTML .trim(); var Canvas = document.createElement('canvas'); Canvas.width = 650; canvg(canvas, svg); if (node.style.position) { Canvas.style.position += node.style.position; Canvas.style.left += node.style.left; .style.top; } nodesToRecover.push({ родительский: родительский узел, дочерний узел: узел }); родительский узел.removeChild (узел); узлыToRemove.push ({ родительский: родительский узел, дочерний: Canvas }); ParentNode.appendChild(canvas }); //Динамически добавляем клонированный узел в тело. $(body).append(cloneDom); html2canvas(cloneDom, { onrendered: function(canvas) { var url =canvas.toDataURL(image/png); window.location.href = url; cloneDom.remove(); // Очистить клонированное содержимое}, фон:#fafafa });
Здесь сначала клонируйте перехватываемый div и установите минимальный индекс z, чтобы избежать некрасивого интерфейса. Затем обрабатывается svg, который был проанализирован выше. Наконец, узел клонирования добавляется к телу Can.
При рендеринге мы можем напрямую использовать location.href для перехода к просмотру изображения, сохранения его или записи URL-адреса в src img и отображения его в интерфейсе, например $('#imgId').attr('src ', URL);
Наконец, только что снятое изображение можно отобразить в интерфейсе:
5. Загрузите изображение, сохраните его в базе данных и получите изображение для отображения в интерфейсе.Теперь, когда URL-адрес получен, его необходимо загрузить на серверную часть, сохранить в базе данных, а затем загрузить в другой отображаемый интерфейс. Обычно я использую URL-адрес для хранения путей к изображениям вместо хранилища больших двоичных объектов.
Поскольку мне нужно получить изображение в другом интерфейсе, я сохранил изображение в каталоге ресурсов на том же уровне, что и веб-приложение. Код выглядит следующим образом:
//Сохраняем изображение и возвращаем путь изображения BASE64Decoder decoder = new BASE64Decoder(); byte[] b = decoder.decodeBuffer(product.getProPic().substring(data:image/png;base64,.length())); ByteArrayInputStream bais = новый ByteArrayInputStream (b); BufferedImage bi1 = ImageIO.read (bais); url = user_resource + File.separator + img + File.separator + product_+UUID.randomUUID().toString().replace(-, )+.png; String totalUrl = System.getProperty(root) + url; новый файл (totalUrl); ImageIO.write (bi1, png, w2); //Сохраняем относительный путь изображения в базе данных int res = productMapper.insertSelective(product); //Добавляем в базу данных;
Поскольку здесь задействована другая логика, включена только часть кода.
BASE64Decoder используется здесь для хранения изображений. После получения изображения нам нужно использовать подстроку для перехвата содержимого data:image/png;base64, поскольку ниже указан URL-адрес изображения: url.substring(data:image/png;base64,.length())
.
Что касается пути, URL-адрес в приведенном выше коде — это контент, который я сохранил в базе данных, а totalUrl — это реальный путь, сохраненный во время фактической операции записи ImageIO. Корневой каталог проекта, полученный методом getProperty(), может быть. настроено в web.xml. Можно использовать следующий контент, а затем System.getProperty(root).
<!-- Настройте систему для получения корневого каталога проекта--><context-param> <param-name>webAppRootKey</param-name> <param-value>root</param-value></context-param ><listener > <listener-class> org.springframework.web.util.WebAppRootListener </listener-class></listener>
Теперь URL изображения хранится в базе данных, а само изображение хранится в каталоге проекта под tomcat.
Наконец, чтобы получить его из интерфейса, просто добавьте имя проекта перед текущим URL-адресом < img class =depot-img src =<%=request.getContextPath()%>/`+e.proPic+` >
.
Затем вы можете увидеть картинку, отображаемую в интерфейсе:
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.