How to use JavaScript to implement screenshot function

WBOY
Release: 2023-05-16 14:07:06
forward
1908 people have browsed it

1. The media type of Blob must be "image/svg xml"

2. A svg element is required

3. Insert a # inside the svg element ## foreignObject Element

4. Put HTML that conforms to the specification into the foreignObject element

Converting dom to canvas is as simple as the above steps. The following is a simple demo given in the document:

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
<canvas id="canvas"  width="200" height="200">
</canvas>
<script>
 var canvas = document.getElementById('canvas');
 var ctx = canvas.getContext('2d');
 var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
  '<foreignObject width="100%" height="100%">' +
  '<div xmlns="http://www.w3.org/1999/xhtml" >' +
  '<em>I</em> like ' +
  '<span >' +
  'cheese</span>' +
  '</div>' +
  '</foreignObject>' +
  '</svg>';
 var DOMURL = window.URL || window.webkitURL || window;
 var img = new Image();
 var svg = new Blob([data], {type: 'image/svg+xml'});
 var url = DOMURL.createObjectURL(svg);
 img.onload = function() {
  ctx.drawImage(img, 0, 0);
  DOMURL.revokeObjectURL(url);
 }
 img.src = url;
</script>
</body>
</html>
Copy after login
Copy the code and run it. Wow, it’s so cool. Two lines of cool word art appear on the browser!

Well, it turns out that converting dom to canvas is so easy? Then I use

document.body.innerHTML to take out all the DOM in the body, and then put it in the foreignObject element. Isn’t it OK and the entire page is intercepted?

The demo is just a Hello World, but the Dom structure in the actual project is much more complicated than this. For example, external style sheets, pictures, and some tags may not comply with the xml specification (such as Missing closing tag, etc.). Here is a simple example. .container does not use inline styles, but is defined in the style tag. The font is red. After it is converted into an image, the style does not take effect.

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <style>
  .container {
   color: red;
  }
 </style>
</head>
<body>
<div class="container" >
 Hello World!
</div>
<canvas id="canvas"  width=200" height="200">
</canvas>
<script>
 var canvas = document.getElementById('canvas');
 var ctx = canvas.getContext('2d');
 var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
  '<foreignObject width="100%" height="100%">' +
  '<div xmlns="http://www.w3.org/1999/xhtml" >' +
  document.querySelector('.container').innerHTML +
  '</div>' +
  '</foreignObject>' +
  '</svg>';
 var DOMURL = window.URL || window.webkitURL || window;
 var img = new Image();
 var svg = new Blob([data], {type: 'image/svg+xml'});
 var url = DOMURL.createObjectURL(svg);
 img.onload = function() {
  ctx.drawImage(img, 0, 0);
  DOMURL.revokeObjectURL(url);
 }
 img.src = url;
</script>
</body>
</html>
Copy after login
Since external styles do not take effect, we can traverse all DOM elements through JS and add all styles to inline styles through the element.style object. This idea sounds good, but I really can't write the function that converts external styles into inline styles. The demand is tight, and I don't have much time to mess around, so I want to look for any ready-made libraries. So I went to Google again. Fortunately, I found a library called html2canvas at once. It is a great library, very powerful, but very simple to use. With such a simple method, I can take a screenshot of my entire page:

function convertHtml2Canvas() {
  html2canvas(document.body, {
   allowTaint: false,
   taintTest: true
  }).then(function(canvas) {
   document.body.appendChild(canvas);
  }).catch(function(e) {
   console.error('error', e);
  });
 }
Copy after login
Currently there is another problem, that is, this method intercepts the entire page by default (that is, it will use your innerHeight and innerWidth as boundaries, and there will be a lot of white space). However, my deck only occupies A small part of the page, I only want the deck part. In fact, it is easier to handle if we already have the canvas, we can process it. The general idea is: 1. Convert the canvas object obtained above into a Blob and put it into an img element. Then draw img.src into canvas. At this time, calling the

canvas.drawImage method can intercept the content we want. The following two functions convert canvas to image and vice versa.

// Converts canvas to an image
 function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL("image/png", 0.1);
  return image;
 }
 // Converts image to canvas; returns new canvas element
 function convertImageToCanvas(image, startX, startY, width, height) {
  var canvas = document.createElement("canvas");
  canvas.width = width;
  canvas.height = height;
  canvas.getContext("2d").drawImage(image, startX, startY, width, height, 0, 0, width, height);
  return canvas;
 }
Copy after login
Then, change the convertHtml2Canvas we wrote above to the following:

function convertHtml2Canvas() {
  html2canvas(document.body, {
   allowTaint: false,
   taintTest: true
  }).then(function(canvas) {
   var img = convertCanvasToImage(canvas);
   document.body.appendChild(img);
   img.onload = function() {
    img.onload = null;
    canvas = convertImageToCanvas(img, 0, 0, 384, 696);
    img.src = convertCanvasToImage(canvas).src;
    $(img).css({
     display: 'block',
     position: 'absolute',
     top: 0,
     left: 400 + 'px'
    });
   }
  }).catch(function(e) {
   console.error('error', e);
  });
 }
Copy after login
At this time, some part of the content of its page can be intercepted. The effect is like a deck sharing test page. The left part of the page is a DOM structure, and the right part is an image converted using html2canvas.

The above is the detailed content of How to use JavaScript to implement screenshot function. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!