preface

Recently, I met a requirement in the project, and I converted the activity page into a poster picture and shared it with others. When doing this requirement, I tried the following two solutions, based on which I made the following records and shares.

Methods a html2canvas

Usage:

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        #poster{
            width: 700px; 
            height: 500px;
            background-color: green;
        }
    </style>
    <script type="text/javascript" src="http://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
    <script type="text/javascript">
        function takeScreenshot() {
            const node = document.getElementById('poster')
            html2canvas(node, {
                useCORS: true.height: node.offsetHeight,
                width: node.offsetWidth,
                scrollY: 0.scrollX: 0
            }).then(async (canvas) => {
                let oImg = new Image();
                oImg.src = canvas.toDataURL();  // Export the image
                document.body.appendChild(oImg);  // Add the generated image to the body})}</script>
</head>
<body>
    <div id="poster">
        <input type="button" value="Capture" onclick="takeScreenshot()">
    </div>
</body>
</html>
Copy the code

Notes:

  1. The resulting image is blurred

Sometimes we will find that some parts of the exported image do not look as clear as the original image, but this is actually because you used the background image. The solution is simple: just use itThe label will be fine

  1. The resulting image has a white border

In the configuration item, set backgroundColor to NULL

  1. Generated images are not displayed

This is one of the most common bugs, and it’s basically because images cross domains, and it’s basically adding two configurations to the method

allowTaint: true.useCORS: true 
Copy the code

Another way to solve this problem is to convert cross-domain images to Base64.

  1. PNG images are not transparent

Sometimes you can use a transparent PNG image as a background image, but the resulting image is not transparent. This is because html2Canvas generates a white background color by default, so the exported image will also have a white background color. The solution is to add a configuration item (in fact, experiments have found that any string that is not a color type will work).

backgroundColor: 'transparent'
Copy the code
  1. The generated image loads with flashing effect

First let the generated image hidden, add the image loading state, such as the image generated after the show.

GitHub

The official documentation

Methods two dom – to – image

Main methods of use:

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        #poster{
            width: 700px; 
            height: 500px;
            background-color: green;
        }
    </style>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"></script>
    <script type="text/javascript">
        function takeScreenshot() {
            const node = document.getElementById('poster')
            domtoimage.toPng(node)
            .then((dataUrl) = > {
                var img = new Image();
                img.src = dataUrl;
                document.body.appendChild(img);
            })
            .catch((error) = > {
                console.error('oops, something went wrong! ', error);
            });
        }
    </script>
</head>
<body>
    <div id="poster">
        <input type="button" value="Capture" onclick="takeScreenshot()">
    </div>
</body>
</html>
Copy the code

1. Domtoimage. ToPng (…). ; Convert the node to a PNG image.

  function takeScreenshot() {
      const node = document.getElementById('poster')
      domtoimage.toPng(node)
      .then((dataUrl) = > {
          var img = new Image();
          img.src = dataUrl;
          document.body.appendChild(img);
      })
      .catch((error) = > {
          console.error('oops, something went wrong! ', error);
      });
  }
Copy the code

2. Domtoimage. ToJpeg (…). ; Convert the node to a JPG image.

  function takeScreenshot() {
      const node = document.getElementById('poster')
      domtoimage.toJpeg(node, { quality: 0.95 })
      .then((dataUrl) = > {
          var img = new Image();
          img.src = dataUrl;
          document.body.appendChild(img);
      })
      .catch((error) = > {
          console.error('oops, something went wrong! ', error);
      });
  }
Copy the code

3. Domtoimage. ToSvg (…). ; The node is converted to an SVG image, and the generated images are in Base64 format.

  function filter (node) {
      return(node.tagName ! = ='i');
  }
  function takeScreenshot() {
      const node = document.getElementById('poster')
      domtoimage.toSvg(node, { filter: filter })
      .then((dataUrl) = > {
          var img = new Image();
          img.src = dataUrl;
          document.body.appendChild(img);
      })
      .catch((error) = > {
          console.error('oops, something went wrong! ', error);
      });
  }
Copy the code

4. Domtoimage. ToBlob (…). ; Convert the node to binary format, which allows you to download the image directly.

  function takeScreenshot() {
      const node = document.getElementById('poster')
      domtoimage.toBlob(node)
      .then((blob) = > {
      	window.saveAs(blob, 'poster.png');
      })
      .catch((error) = > {
          console.error('oops, something went wrong! ', error);
      });
  }
Copy the code

5. Domtoimage. ToPixelData (…). ; Gets the raw pixel values returned as Uint8Array arrays with 4 array elements representing one pixel, or RGBA value. This method is also useful for writing shader colors in WebGL.

  function takeScreenshot() {
      const node = document.getElementById('poster')
      domtoimage.toPixelData(node)
      .then((pixels) = > {
      	for (var y = 0; y < node.scrollHeight; ++y) {
          for (var x = 0; x < node.scrollWidth; ++x) {
            pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x);
            /* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0.. 255 * /
            pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
          }
        }
      })
      .catch((error) = > {
          console.error('oops, something went wrong! ', error);
      });
  }
Copy the code

Notes:

  1. The DOM element used to generate an image cannot be displayed: None or opacity:0. We can use z-index to put it under other elements; Or use absolute positioning to put it out of sight of a div container, and then the container sets overflow:hidden
  2. The parent elements of the DOM element used to generate the image cannot display: None
  3. Synthesizing 1 and 2 means that the DOM elements used to generate the image are themselves visible and can be sized, but do not need to appear in view
  4. The page cannot have a style that hides the iframe, such as iframe{display:none}
  5. The generated image is automatically appented to the DOM element to be generated. The class name is Dom2img-result. If you do not want to show the image to the user, set the image style to opacity:0

GitHub