최근 프로젝트를 작성할 때 페이지의 스크린샷 기능을 구현할 수 있는 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를 가로챌 때 div에 svg 태그가 있으면 일반적인 상황에서는 가로챌 수 없습니다. 예를 들어 순서도를 가로채면 다음과 같은 결과가 나타납니다.
흐름도의 선이 가로채지 않는, 즉 svg가 가로채지지 않는 것을 볼 수 있습니다. 이때 해결 방법은 svg를 캔버스로 변환한 후 스크린샷을 찍어 코드를 직접 업로드하는 것입니다.
여기의 각 루프는 모든 svg 태그를 반복하고 모두 캔버스로 변환하는 것입니다.
if (typeof html2canvas !== 'undefine') { //svg 처리는 다음과 같습니다. var nodeToRecover = []; var nodeToRemove = [] var svgElem = cloneDom.find('svg'); ( 인덱스, 노드) { var parentNode = node.parentNode var svg = node.outerHTML.trim(); var canvas = document.createElement('canvas'); canvas.width = 650; canvg(canvas, svg); if (node.style.position) += node.style .position; canvas.style.left += node.style.left; canvas.style.top += node.style.top } nodeToRecover.push({ 부모: parentNode, 자식: 노드 }); parentNode.removeChild(노드); nodeToRemove.push({ parent: parentNode, child: canvas });여기에는 Canvg.js와 해당 종속 파일 rgbcolor.js가 필요합니다. 인터넷에서 직접 다운로드하거나 직접 가져올 수 있습니다.
3. 배경 투명성 문제기본적으로 투명하기 때문에 이것은 실제로 매우 간단합니다. html2canvas에는 다음과 같이 배경색을 추가하는 배경 매개변수가 있습니다.
html2canvas(cloneDom, { onrendered: function(canvas) { var url =canvas.toDataURL(image/png); }, background:#fafafa}); 4. 보이는 부분만 담을 수 있는 문제점가로채야 하는 div가 인터페이스를 초과하면 불완전 가로채기 문제가 발생할 수 있습니다. 위 그림과 같이 콘텐츠가 절반만 숨겨져 있기 때문에 html2canvas에서는 가로채기를 할 수 없습니다. 숨겨진 DOM.
그래서 이때 해결방법은 복제를 이용해서 가로채야 할 부분의 복사본을 페이지 하단에 배치한 후 html2canvas를 이용하여 가로채기가 완료된 후 이 부분을 제거하는 것입니다. 내용. 전체 코드는 다음과 같습니다.
function showQRCode() { scrollTo(0, 0); //노드 복제, 기본값은 false입니다. 즉, 메소드 속성은 복사되지 않으며 true는 모두 복사됩니다. var cloneDom = $(#d1).clone(true); //복제되는 노드보다 낮은 한 복제된 노드의 z-index 속성을 설정합니다. cloneDom.css({ background-color: #fafafa, 위치: 절대, 상단: 0px, z-index: -1, 높이: 798, 너비: 650 }) if (typeof html2canvas !== 'undefine') { / /다음은 svg의 처리입니다. var nodeToRecover = [] var nodeToRemove = []; cloneDom.find('svg');//divReport는 그림으로 가로채야 하는 dom의 ID입니다. svgElem.each(function (index, node) { var parentNode = node.parentNode; var svg = node.outerHTML .trim(); var canvas = document.createElement('canvas'); canvas.width = 650; canvg(캔버스, svg); if (node.style.position) { canvas.style.position += node.style.position; canvas.style.left += node.style.top += 노드; .style.top; } nodeToRecover.push({ parent: parentNode, child: node }); nodeToRemove.push({ parent: parentNode, child: canvas }); parentNode.appendChild(canvas) }); //복제된 노드를 본문에 동적으로 추가합니다. $(body).append(cloneDom); html2canvas(cloneDom, { onrendered: function(canvas) { var url =canvas.toDataURL(image/png); window.location.href = url ; cloneDom.remove(); // 복제된 콘텐츠 지우기}, background:#fafafa }) } }여기서는 먼저 가로챌 div를 복제하고 보기 흉한 인터페이스가 발생하지 않도록 z-index를 최소로 설정합니다. 그런 다음 위에서 분석한 svg를 처리하면 마지막으로 본문에 복제 노드가 추가됩니다.
onrendered에서는 location.href를 직접 사용하여 이미지를 보거나 저장하거나 img의 src에 URL을 작성하고 $('#imgId').attr('src와 같이 인터페이스에 표시할 수 있습니다. ',url);
마지막으로 방금 캡처한 사진을 인터페이스에 표시할 수 있습니다.
5. 이미지를 업로드하고 데이터베이스에 저장한 후 인터페이스에 표시할 이미지를 얻습니다.이제 URL을 얻었으므로 이를 백엔드에 업로드하고 데이터베이스에 저장한 다음 다른 표시된 인터페이스에 로드해야 합니다. 나는 일반적으로 Blob 저장소 대신 이미지 경로를 저장하기 위해 URL을 사용하는 데 익숙합니다.
다른 인터페이스에서 이미지를 가져와야 하기 때문에 webapp과 동일한 수준의 리소스 디렉터리에 이미지를 저장했습니다.
//그림을 저장하고 그림 경로를 반환합니다. BASE64Decoder decoder = new BASE64Decoder(); byte[] b = decoder.decodeBuffer(product.getProPic().substring(data:image/png;base64,.length())); ByteArrayInputStream bais = new 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는 이미지를 저장하는 데 사용됩니다. 다음은 이미지의 URL인 url.substring(data:image/png;base64,.length()) 이므로 data:image/png;base64의 내용을 가로채기 위해 하위 문자열을 사용해야 합니다. 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 ><리스너 > <리스너-클래스> org.springframework.web.util.WebAppRootListener </listener-class></listener>
이제 이미지의 URL이 데이터베이스에 저장되고 이미지 자체는 tomcat 아래의 프로젝트 디렉터리에 저장됩니다.
마지막으로 인터페이스에서 가져오려면 현재 URL < img class =depot-img src =<%=request.getContextPath()%>/`+e.proPic+` > 앞에 프로젝트 이름을 추가하면 됩니다.
그러면 인터페이스에 표시된 그림을 볼 수 있습니다.
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.