中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用JavaScript怎么實現網頁截圖

發布時間:2021-04-17 17:19:12 來源:億速云 閱讀:158 作者:Leah 欄目:web開發

今天就跟大家聊聊有關使用JavaScript怎么實現網頁截圖,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

Canvas 實現

如何將dom轉換成canvas圖片?自然是要一點點畫到canvas里,想想都是件麻煩事。通過分析github的知名截圖庫 niklasvh/html2canvas (7k+ star)的源碼,梳理了其大致的思路:

  • 遞歸取出目標模版的所有DOM節點,填充到一個rederList,并附加是否為頂層元素/包含內容的容器 等信息

  • 通過z-index postion float等css屬性和元素的層級信息將rederList排序,計算出一個canvas的renderQueue

  • 遍歷renderQueue,將css樣式轉為setFillStyle可識別的參數,依據nodeType調用相對應canvas方法,如文本則調用fillText,圖片drawImage,設置背景色的div調用fillRect等

  • 將畫好的canvas填充進頁面

無論是排序優先級的計算還是從css到canvas的轉換,毫無疑問都是些巨麻煩的事,尤其是放在真實的業務場景里,DOM模版中往往會包含復雜的樣式與排版,html2canvas 足足用了20多個js來實現這層轉換,復雜成度可見一斑。索性,我們不需要再重新造一遍輪子。

使用canvas轉化的話靈活性較高,環境依賴上也只需要確保瀏覽器支持canvas就可以了,但它有個顯著的缺點:慢。原因自然是因為大量的計算與遞歸調用,這是無可避免的。不過html2canvas代碼中大量使用了Promise,所以html2canvas 支持異步操作。

限制:

  • 無法跨域跨域資源

  • 無法渲染iframe,flash等內容,但目前支持svg

值得一提的是,盡管html2canvas主頁表示它還處于實驗室環境,但自14年起便已經被Twitter 等用在了生產環境,所以雖然有諸多限制,穩定性應該還是保障的。

canvas如此復雜,那么有沒有一種更簡單的方法呢?

自然是有的,那便是SVG

SVG實現

首先,svg本來就是矢量圖形;其次,svg是可以用xml描述的;再其次,用來描述svg的標簽里有個 foreignObject標簽,這個標簽可以加載其它命名空間的xml(xhtml)文檔。也就是說,如果使用svg的話,我們不再需要一點點的遍歷,轉換節點;不用再計算復雜的元素優先級,只需要一股腦的將要渲染的DOM扔進<foreignObject></foreignObject>就好了,剩下的就交給瀏覽器去渲染。

讓我們理一理思路:

  • 首先,我們要聲明一個基礎的svg模版,這個模版需要一些基礎的描述信息,最重要的,它要有<foreignObject></foreignObject>這對標簽

  • 將要渲染的DOM模版模版嵌入foreignObject

  • 利用Blob構建svg圖像

  • 取出URL,賦值給

  <div id='text'>
    <h2  >Hello World</h2>
  </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限制的

萬幸,一個昵稱為Christoph Burgmer的小哥寫了一個名為rasterizeHTML.js 的庫,通過一系列的hack技巧替我們繞過了許多限制。我知道你很好奇他是怎么做到的。 簡單來講,rasterizeHTML.js在我們的基礎實現上做了這些hack:

  • 將<img/>的url 轉為 dataURI

  • 將background-color從style中取出,修改url后重新插入樣式表

  • 將link的的樣式通過ajax down下來然后注入<style></sytle>

  • 詳見源碼...

當然, rasterizeHTML.js能幫我們做的也不過是處理資源引用問題和瀏覽器兼容問題,更多的SVG的限制是無法繞過的,該庫的文檔正式列出了足足一整頁的限制,讓人讀完后心中一涼。比如:

  • 跨域資源無法加載

  • 如lazyload等通過js加載的資源無法加載

  • 內聯或js操作background-image無法加載

  • 詳見文檔

思考下rasterizeHTML.js的原理便可理解這些限制無法避免的原因: rasterizeHTML.js只能對已經存在的靜態資源進行處理,而對js動態生成并不能實時處理。

看完上述內容,你們對使用JavaScript怎么實現網頁截圖有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高安市| 乌拉特后旗| 永丰县| 读书| 辽中县| 垣曲县| 观塘区| 社会| 宜都市| 武陟县| 怀仁县| 万源市| 潍坊市| 江油市| 邢台县| 沂南县| 松滋市| 安顺市| 梨树县| 收藏| 杨浦区| 灌云县| 永丰县| 连云港市| 大庆市| 金山区| 朝阳县| 吴堡县| 加查县| 黔江区| 兰溪市| 石河子市| 福贡县| 靖西县| 永清县| 民乐县| 江门市| 射阳县| 乐昌市| 安多县| 达尔|