JavaScript網頁截屏方法,你get到了嘛?

来源:https://www.cnblogs.com/coderhf/archive/2020/06/19/13164104.html
-Advertisement-
Play Games

之前我曾寫過如何將canvas圖形轉換成圖片和下載canvas圖像的方法,這些都是在為這個插件做技術準備。 技術路線很清晰,將網頁的某個區域的內容生成圖像,保持到canvas里,然後將canvas內容轉換成圖片,保存到本地,最後上傳到微博。 我在網上搜尋到html2canvas這個能將指定網頁元素內 ...


之前我曾寫過如何將canvas圖形轉換成圖片和下載canvas圖像的方法,這些都是在為這個插件做技術準備。

技術路線很清晰,將網頁的某個區域的內容生成圖像,保持到canvas里,然後將canvas內容轉換成圖片,保存到本地,最後上傳到微博。

我在網上搜尋到html2canvas這個能將指定網頁元素內容生成canvas圖像的javascript工具。這個js工具的用法很簡單,你只需要將它的js文件引入到頁面里,然後調用html2canvas()函數:

 html2canvas(document.body, {
     onrendered: function(canvas) {
         /* canvas is the actual canvas element,
            to append it to the page call for example
            document.body.appendChild( canvas );
         */
     }
 });

 

這個html2canvas()函數有個參數,上面的例子里傳入的參數是document.body,這會截取整個頁面的圖像。如果你想只截取一個區域,比如對某個p或某個table截圖,你就將這個p或某個table當做參數傳進去。

我最終並沒有選用html2canvas這個js工具,因為在我的實驗過程中發現它有幾個問題。

首先,跨域問題。我舉個例子說明這個問題,比如我的網頁網址是http://www.webhek.com/about/,而我在這個頁面上有個張圖片,這個圖片並不是來自www.webhek.com域,而是來自CDN圖片伺服器www.webhek-cdn.com/images/about.jpg,那麼,這張圖片就和這個網頁不是同域,那麼html2canvas就無法對這種圖片進行截圖,如果你的網站的所有圖片都放在單獨的圖片伺服器上,那麼用html2canvas對整個網頁進行截圖是就會發現所有圖片的地方都是空白。

這個問題也有補救的方法,就是用代理:

 <!DOCTYPE html>
 <html>
     <head>
         <meta charset="utf-8">
         <title>html2canvas php proxy</title>
         <script src="html2canvas.js"></script>
         <script>
         //<![CDATA[
         (function() {
             window.onload = function(){
                 html2canvas(document.body, {
                     "logging": true, //Enable log (use Web Console for get Errors and Warnings)
                     "proxy":"html2canvasproxy.php",
                     "onrendered": function(canvas) {
                         var img = new Image();
                         img.onload = function() {
                             img.onload = null;
                             document.body.appendChild(img);
                         };
                         img.onerror = function() {
                             img.onerror = null;
                             if(window.console.log) {
                                 window.console.log("Not loaded image from canvas.toDataURL");
                             } else {
                                 alert("Not loaded image from canvas.toDataURL");
                             }
                         };
                         img.src = canvas.toDataURL("image/png");
                     }
                 });
             };
         })();
         //]]>
         </script>
     </head>
     <body>
         <p>
             <img alt="google maps static" src="http://maps.googleapis.com/maps/api/staticmap?center=40.714728,-73.998672&zoom=12&size=800x600&maptype=roadmap&sensor=false">
         </p>
     </body>
 </html>

 

這個方法只能用在你自己的伺服器里,如果是對別人的網頁截圖,還是不行。

試驗的過程中還發現用html2canvas截屏出來的圖像有時會出現文字重疊的現象。我估計是因為html2canvas在解析頁面內容、處理css時不是很完美的原因。

最後,我在火狐瀏覽器的官方網站上找到了drawWindow()這個方法,這個方法和上面提到html2canvas不同之處在於,它不分析頁面元素,它只針對區域,也就是說,它接受的參數是四個數字標誌的區域,不論這個區域中什麼地方,有沒有頁面內容。

 void drawWindow(
   in nsIDOMWindow window,
   in float x, 
   in float y,
   in float w,
   in float h,
   in DOMString bgColor,
   in unsigned long flags [optional]
 );

 

這個原生的JavaScript方法看起來非常的完美,正是我需要的,但這個方法不能使用在普通網頁中,因為火狐官方發現這個方法會引起有安全漏洞,在這個bug修複之前,只有具有“Chrome privileges”的代碼才能使用這個drawWindow()函數。

雖然有很大的限制,但周折一下還是可以用的,在我開發的火狐addon插件中,main.js就是具有“Chrome privileges”的代碼。我在網上發現了一段火狐插件SDK里自帶代碼樣例:

 var window = require('window/utils').getMostRecentBrowserWindow();
 var tab = require('tabs/utils').getActiveTab(window);
 var thumbnail = window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
 thumbnail.mozOpaque = true;
 window = tab.linkedBrowser.contentWindow;
 thumbnail.width = Math.ceil(window.screen.availWidth / 5.75);
 var aspectRatio = 0.5625; // 16:9
 thumbnail.height = Math.round(thumbnail.width * aspectRatio);
 var ctx = thumbnail.getContext("2d");
 var snippetWidth = window.innerWidth * .6;
 var scale = thumbnail.width / snippetWidth;
 ctx.scale(scale, scale);
 ctx.drawWindow(window, window.scrollX, window.scrollY, snippetWidth, snippetWidth * aspectRatio, "rgb(255,255,255)");
 // thumbnail now represents a thumbnail of the tab

 

這段代碼寫的非常清楚,只需要依據它做稍微的修改就能適應自己的需求。

更多學習內容觀看我的知乎打造全網web高級前端工程師資料庫(總目錄)看完學的更加快,知識更牢固。你值得擁有(持續更新)~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • TypeScript 是一種由微軟開發的自由和開源的編程語言。它是 JavaScript 的一個超集,而且本質上向這個語言添加了可選的靜態類型和基於類的面向對象編程。 TypeScript 提供最新的和不斷發展的 JavaScript 特性,包括那些來自 2015 年的 ECMAScript 和未來 ...
  • 1、標準流(普通流/文檔流) 標準流就是標簽按照規定好的預設方式排列 (1)塊級元素會獨占一行,按照從上到下的方式排列 (2)行內元素會按照順序,從左到右的順序進行排列,遇到父元素則自動換行 (3)縱向排列標準流,橫向排列用浮動 2、浮動的簡單應用 (1)讓多個塊級元素水平排列在一行(這裡將行內元素 ...
  • 我們在寫筆試題的時候,經常碰到涉及隱式轉換的題目,例如 "1" + 2 obj + 1 [] == ![] [null] == false 和 == = 叫做嚴格運算符,對象類型指向地址相同或原始類型( 數值、字元串、布爾值)值相同;叫做相等運算符,類型不同會進行轉化再比較,undefined、nu ...
  • document.write() 用法 在JavaScript中document.write()函數可以向文檔寫入HTML表達式或JavaScript代碼,用法“document.write(exp1,exp2,exp3,....)”,該函數可接受任何多個參數,並將其寫入文檔中。 document. ...
  • 什麼是無頭瀏覽器(headless browser)? 無頭瀏覽器是指可以在圖形界面情況下運行的瀏覽器。我可以通過編程來控制無頭瀏覽器自動執行各種任務,比如做測試,給網頁截屏等。 為什麼叫“無頭”瀏覽器? “無頭”這個詞來源於最初的“無頭電腦(Headless computer)”。維基百科關於的 ...
  • 鏈接生成二維碼 1.npm安裝 npm install --save qrcodejs2 2.引入 import QRCode from 'qrcodejs2' 3.生成二維碼 new QRCode('qrcode', { // 傳入容器id text: url, // 鏈接(必填) width: ...
  • 優秀的前端開發工程師要在知識體繫上要有廣度和深度,要具備快速學習的能力。 前端開發工程師不僅要掌握基本的Web前端開發技術,網站性能優化、及一些基礎知識,而且要學會運用各種工具進行輔助開發以及理論層面的知識,包括代碼的可維護性、分層語義模板和瀏覽器分級支持等。 一、前端工程師至少要滿足四類客戶的需求 ...
  • 需求:當按鍵盤enter鍵和鍵盤左右鍵時,左右切換頁面卡片並讀取卡片上的信息 一、獲取鍵盤對應的keycode keyCode 實際鍵值 48到57 0到9 65到90 a到z(A到Z) 112到135 F1到F24 8 BackSpace(退格) 9 Tab 13 Enter(回車) 20 Cap ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...