Heim >Betrieb und Instandhaltung >Sicherheit >So verwenden Sie JavaScript, um die Screenshot-Funktion zu implementieren

So verwenden Sie JavaScript, um die Screenshot-Funktion zu implementieren

WBOY
WBOYnach vorne
2023-05-16 14:07:061951Durchsuche

1. Der Medientyp von Blob muss „image/svg“ sein. 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. Ein SVG-Element ist erforderlich.

3 SVG-Element

4. Fügen Sie HTML, das der Spezifikation entspricht, in das ForeignObject-Element ein. Das Konvertieren von Dom in Canvas ist so einfach wie die oben genannten Schritte. Das Folgende ist eine einfache Demo im Dokument: 🎜rrree🎜 Kopieren Sie den Code und führen Sie ihn aus. Wow, es ist so cool, dass im Browser zwei Zeilen mit cooler Wortkunst angezeigt werden. 🎜🎜Nun, es stellt sich heraus, dass die Konvertierung von Dom in Canvas so einfach ist? Dann verwende ich document.body.innerHTML , um das gesamte DOM im Körper herauszunehmen und es dann in das ForeignObject-Element einzufügen. Ist das nicht in Ordnung und die gesamte Seite wird erfasst?
🎜🎜Die Demo ist nur eine Hello World, aber die Dom-Struktur im eigentlichen Projekt ist viel komplizierter. Beispielsweise entsprechen externe Stylesheets, Bilder und einige Tags möglicherweise nicht der XML-Spezifikation (z wie das Fehlen schließender Tags) warten). Hier ist ein einfaches Beispiel. .container verwendet keine Inline-Stile, sondern ist im Stil-Tag definiert. Nach der Konvertierung in ein Bild wird der Stil nicht wirksam. 🎜
// 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;
 }
🎜Da externe Stile nicht wirksam werden, können wir alle DOM-Elemente über JS durchlaufen und alle Stile über das element.style-Objekt zu Inline-Stilen hinzufügen. Diese Idee hört sich gut an, aber ich kann wirklich nicht die Funktion schreiben, die externe Stile in Inline-Stile umwandelt. Die Nachfrage ist gering und ich habe nicht viel Zeit zum Herumspielen, deshalb möchte ich nach fertigen Bibliotheken suchen. Also ging ich noch einmal zu Google. Glücklicherweise habe ich sofort eine Bibliothek namens html2canvas gefunden. Es ist eine großartige Bibliothek, sehr leistungsfähig, aber sehr einfach zu verwenden. Mit einer so einfachen Methode kann ich einen Screenshot meiner gesamten Seite erstellen: 🎜
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);
  });
 }
🎜Derzeit ist dass diese Methode standardmäßig die gesamte Seite abfängt (das heißt, sie verwendet Ihre innerHeight und innerWidth als Grenzen und es wird viel Leerraum geben, mein Deck nimmt jedoch nur einen kleinen Teil der Seite ein). Ich möchte nur den Deckteil. Tatsächlich ist es einfacher zu handhaben, wenn wir die Leinwand bereits haben und sie verarbeiten können. Die allgemeine Idee ist: 1. Konvertieren Sie das oben erhaltene Canvas-Objekt in einen Blob und fügen Sie ihn in ein img-Element ein. Zeichnen Sie dann img.src in die Leinwand. Zu diesem Zeitpunkt kann der Aufruf der Methode canvas.drawImage den gewünschten Inhalt abfangen. Die folgenden zwei Funktionen konvertieren Leinwand in Bild und umgekehrt. 🎜rrreee🎜Ändern Sie dann das oben geschriebene „convertHtml2Canvas“ wie folgt: 🎜rrreee🎜Zu diesem Zeitpunkt kann ein Teil des Inhalts der Seite abgefangen werden. Der Effekt ähnelt einer Deck-Sharing-Testseite. Der linke Teil der Seite ist eine DOM-Struktur und der rechte Teil ist ein mit html2canvas konvertiertes Bild. 🎜

Das obige ist der detaillierte Inhalt vonSo verwenden Sie JavaScript, um die Screenshot-Funktion zu implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen