簡単にjsを分析してウェブページのスクリーンショットの2種類の方式を実現します。


Web端末のスクリーンショット(写真を生成する)は高周波の需要ではなく、資料も多くないので、調べても、CanvasとSVGの2つの実現案です。原理は大体似ています。本当の意味でのスクリーンショットではなく、DOMを画像に変換しますが、実現方法は全く違っています。
キャンバス実現
どうやってdomをcanvasの写真に変換しますか?もちろん少しずつキャンバスに描いていくのです。考えるのも面倒くさいです。githubの有名なカット図庫niklasvh/html 2 canvas(7 k+star)のソースコードを分析することによって、大体の考えを整理しました。
  • は、対象テンプレートのすべてのDOMノードを再帰的に取り出し、1つのreder Listに充填し、最上位の要素/コンテンツを含むコンテナなどの情報を付加する
  • は、z-indx postion froatなどのcss属性と要素の階層情報を通じてreder Listを並べ替えて、canvasのrenderQue
  • を計算しました。
  • はrenderQueを巡回して、cssスタイルをset FillSteyle識別可能なパラメータに変えて、nodeTypeによって呼応するcanvas方法を呼び出して、テキストのようにfillTextを呼び出して、画像drawImage、背景色のdivを設定してfillct Rectなど
  • を呼び出します。
  • で描いたcanvasをページ
  • に充填します。
    優先度の計算もcssからcanvasへの転換も、間違いなく大きなトラブルであり、特に実際のビジネスシーンにおいては、DOMモデルには複雑な様式とレイアウトが含まれており、html 2 canvasは20以上のjsを使ってこの層の転換を実現しており、複雑さが見られます。いっそのこと、私たちはもう一度車輪を作る必要はないです。
    canvasを使うと柔軟性が高く、環境に依存してもブラウザがcanvasをサポートしてくれるだけでいいですが、著しい欠点があります。遅いです。その理由は当然、大量の計算と再帰的な呼び出しのために避けられない。ただし、httml 2 canvasコードにはPromiseが多く使われていますので、html 2 canvasは非同期操作をサポートしています。
    制限:
  • はドメインをまたぐことができません。
  • はiframe、flashなどのコンテンツをレンダリングできませんが、svg
  • は現在サポートされています。
    ちなみに、httml 2 canvasのホームページではまだ実験室の環境にあるとしていますが、14年からTwitterなどで生産環境に使われていますので、多くの制限がありますが、安定性はまだ保障されています。
    canvasは複雑ですが、もっと簡単な方法がありますか?
    もちろんあります。それはSVGです。
    SVG実装
    まず、svgはもともとベクトルパターンです。次に、svgはxmlで説明できる。次に、svgを記述するタグの中にforeignObjectタグがあります。このラベルは他の名前空間のxml(x)文書を読み込むことができます。つまり、svgを使うなら、私達はもうちょっとの遍歴、転換ノードを必要としません。複雑な要素優先度を計算しなくてもいいです。レンダリングするDOMをに捨てればいいです。あとはブラウザにレンダリングします。
    考えを整理しましょう。
  • まず、基本的なsvgモデルを宣言したいです。このモデルはいくつかの基礎的な説明情報が必要です。最も重要なのは、「foreignObject」というラベル
  • です。
  • レンダリングするDOMテンプレートをforeignObject
  • に埋め込む。
  • は、Blobを利用してsvg画像
  • を構築する。
  • はURLを取り出して、
  • に割り当てます。
    
      <div id='text'>
        <h1 style="background-color: #ccc;width: 200px;height: 200px;" >Hello World</h1>
      </div>
    
    //     chrome     
    function html2Svg (domStr) { 
          //       
          var svgXML=
          `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
            <foreignObject width="100%" height="100%">${generateXML(html)}</foreignObject>
           </svg>`
          //  Blob  svg
          var svg = new Blob([svgXML], {type: 'image/svg+xml'})
          //  DOMURL.createObjectURL    
          var url = window.URL.createObjectURL(svg);
          var img = new Image()
          img.src = url
          return img
        }
    
    //   `foreignObject`    XML  ,
    //        DOM     
    function generateXML (domStr) { 
        var doc = document.implementation.createHTMLDocument('');
          doc.write(html);
          doc.documentElement.setAttribute('xmlns', doc.documentElement.namespaceURI);
          doc = parseStyle(doc)
          console.log(doc)
          html = (new XMLSerializer).serializeToString(doc).replace('<!DOCTYPE html>','');
          return html
    }
    
    
    この考え方で実現するのは非常に簡単で、複雑な計算と再帰性がなく、レンダリング速度は自然に前者より優れていると見られます。しかしsvgを使うには、多くの制限が必要です。一つの最も深刻な問題は、SVGが外部資源をロードできない、すなわちsvgの中で、それともcssの中の背景図であろうと、これらの資源は全部ロードできないということです。canvasを使って実現する時、私達はnodeの一つのnodeで描くので、資源の引用の問題が存在しません。しかしsvgを使って実現して、私達が文書をSVGに渡してもう一度レンダリングすることに相当して、これは私達にとって実は制御できないブラックボックスの操作で、SVGの制限を受けたのです。
    幸い、Christph Burgmerというニックネームのお兄さんがレジスターizeHTML.jsというライブラリを書いてくれました。一連のhack技術を通じて、いろいろな制限を回避してくれました。彼がどうやってできたのか気になります。簡単に言えば、rasterizeHTML.jsは私達の基礎の実現の上でこれらのhackをしました。

  • のurlをdataURI
  • に変えます。
  • はバックグランドカラーをスタイリングから取り出し、urlを修正してスタイルテーブル
  • を新たに挿入する。
  • は、linkのスタイルをajax downを通して降りて