Maison  >  Article  >  Opération et maintenance  >  Comment utiliser JavaScript pour implémenter la fonction de capture d'écran

Comment utiliser JavaScript pour implémenter la fonction de capture d'écran

WBOY
WBOYavant
2023-05-16 14:07:061854parcourir

1. Le type de média du Blob doit être "image/svg+xml" image/svg+xml"

2.需要一个 svg 元素

3.在 svg 元素里面插入一个 foreignObject 元素

4.在 foreignObject 元素里面放入符合规范的 html

把dom转成canvas就这么简单,就上面几个步骤。下面是文档给出的一上简单的demo:

<!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>

复制代码,运行一下,哇,帅呆了,浏览器上出现了超酷的两行艺术字呢!

嗯,原来dom转成canvas这么简单啊?那我通过 document.body.innerHTML 把body里面的所有dom取出来,然后放到 foreignObject 元素里面,不就OK了、把整个页面都截取下来了吗?

demo仅仅是个Hello World,但是实际项目中的Dom结构比这个复杂多了,比如,引入了外部样式表、图片、而且还可能某些标签不符合xml规范(如缺少闭合标签等)。下面的举个简单的例子,.container不是使用行内样式的,而是在style标签里面定义,字体红色,转成图片后,样式不生效。

<!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>

既然外部样式不生效,那我们可以通过JS遍历所有的dom元素,把全部的样式通过element.style对象添加到行内样式啊。这个思路听起来不错,但是,实现这个把外部样式转成行内样式的函数我还真写不出来啊。需求比较紧,也没有那 多时间去瞎折腾了,所以,就想找找有没有现成的库。于是又去google一下。很幸运, 一下子就搜到了一个叫做html2canvas的库,非常棒的一个库,很强大、但用法非常简单.就这么简单的方法,就可以把我的整个页面截图下来了:

function convertHtml2Canvas() {
  html2canvas(document.body, {
   allowTaint: false,
   taintTest: true
  }).then(function(canvas) {
   document.body.appendChild(canvas);
  }).catch(function(e) {
   console.error('error', e);
  });
 }

目前还有一个问题,就是这种方法默认是把整个页面截取下来的(就是说,会以你的innerHeight和innerWidth为边界,会存在大量的空白),可是,我的卡组只是占了页面的一小部分,我只想要卡组的部分啊。其实已经有了canvas就好办了,我们可以对它进行处理啊。大概思路是:1.把上面得到的canvas对象转成Blob并放到一个img元素。然后再把img.src绘制到canvas里面。这时候调用canvas.drawImage

2 Un élément svg est requis

3 Insérez un élément ForeignObject dans le fichier. Élément svg

4. Mettez du HTML conforme à la spécification dans l'élément ForeignObject🎜🎜La conversion de dom en canevas est aussi simple que les étapes ci-dessus. Ce qui suit est une démo simple donnée dans le document : 🎜
// 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;
 }
🎜 Copiez le code et exécutez-le, c'est trop cool. Deux lignes d'art de mots sympas apparaissent sur le navigateur ! 🎜🎜Eh bien, il s'avère que convertir un dom en toile est si simple ? Ensuite, j'utilise document.body.innerHTML pour supprimer tout le DOM du corps, puis je le mets dans l'élément ForeignObject. N'est-ce pas OK et la page entière est interceptée ?
🎜🎜La démo n'est qu'un Hello World, mais la structure Dom dans le projet réel est beaucoup plus compliquée que cela. Par exemple, les feuilles de style externes, les images et certaines balises peuvent ne pas être conformes à la spécification XML (telles que celles-ci). comme le manque de balises de fermeture) attendez). Voici un exemple simple. .container n'utilise pas de styles en ligne, mais est défini dans la balise de style. Une fois convertie en image, le style ne prendra pas effet. 🎜
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);
  });
 }
🎜Étant donné que les styles externes ne prennent pas effet, nous pouvons parcourir tous les éléments DOM via JS et ajouter tous les styles aux styles en ligne via l'objet element.style. Cette idée semble bonne, mais je ne peux vraiment pas écrire la fonction qui convertit les styles externes en styles en ligne. La demande est forte et je n'ai pas beaucoup de temps pour m'amuser, je souhaite donc rechercher des bibliothèques prêtes à l'emploi. Je suis donc retourné sur Google. Heureusement, j'ai tout de suite trouvé une bibliothèque appelée html2canvas. C'est une excellente bibliothèque, très puissante, mais très simple à utiliser. Avec une méthode aussi simple, je peux prendre une capture d'écran de ma page entière : 🎜rrreee🎜Actuellement. que cette méthode intercepte la page entière par défaut (c'est-à-dire qu'elle utilisera votre innerHeight et innerWidth comme limites, et il y aura beaucoup d'espace blanc. Cependant, mon deck n'occupe qu'une petite partie de la page, je le fais). je veux juste la partie deck. En fait, c'est plus facile à manipuler si on a déjà la toile, on peut la traiter. L'idée générale est la suivante : 1. Convertir l'objet canvas obtenu ci-dessus en un Blob et le mettre dans un élément img. Dessinez ensuite img.src dans le canevas. À ce stade, l'appel de la méthode canvas.drawImage peut intercepter le contenu souhaité. Les deux fonctions suivantes convertissent le canevas en image et vice versa. 🎜rrreee🎜Ensuite, remplacez le convertHtml2Canvas que nous avons écrit ci-dessus par ce qui suit : 🎜rrreee🎜À ce stade, une partie du contenu de sa page peut être interceptée. L'effet est comme une page de test de partage de deck. La partie gauche de la page est une structure DOM et la partie droite est une image convertie à l'aide de html2canvas. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer