使用 JavaScript 截屏


經常在微博上看到很多內容使用的什么長微博截圖,並且截圖上還附加了很多其他的信息。之前對純前端截圖有些研究,正好本博客有這個需求,今天就把這東西實現了下。

需要聲明的是,JavaScript 目前還不能實現網頁截屏,就算以后能夠實現,也一定是瀏覽器提供了相關接口,JS 去調用這些接口。既然不能截屏,那我們能做的只有通過拿到像素點的信息來”拼湊”圖片。

用過 phantomJS 的同學都知道,它提供了一個截屏函數,通過它可以整屏獲取頁面截圖,而且他支持的格式也比較多:JPG/PNG/GIF/PDF。通過簡單的兩句命令就可以把一個網頁截取下來:

// render.js
var webPage = require('webpage');
var page = webPage.create();

page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.taobao.com", function start(status) {
  page.render('taobao_home.jpeg', {format: 'jpeg', quality: '100'});
  phantom.exit();
});

安裝 phantomjs 之后執行下上面的文件:

phantomjs render.js

你會發現,一張寬度很窄的淘寶首頁圖就保存到了同目錄下的 taobao_home.jpeg 中。也有同學使用 phantomjs 做了很多有意思的東西,比如每隔 100ms 截圖,然后對比圖像之間的差異,分析網頁的加載情況和性能問題,甚至做網頁的監控。好吧,話題收回來,繼續說說其他的截屏方式,關於 phantomjs 可以移步到官網學習。

能夠導出圖片的,目前只有 canvas。頁面上的元素,除了圖片、視音頻、SVG等,其他都是文字,都可以使用 css 樣式變換出來。我們知道,在 canvas 中是可以繪制圖片和文字的,那么問題就很好解決了。

  • 遍歷頁面的所有元素,提取DOM數
  • 獲取渲染之后的每個 DOM 節點的內聯、外鏈 CSS 屬性
  • 將樣式轉換成 canvas 的屬性,利用 offset 等屬性輔助擺放位置,將節點對應到 canvas 上

這個方案比較粗糙,但是對於簡單的頁面,以上操作就能導出一張幾乎與原狀一模一樣的圖片。當然,我們想到的,也有人實現出來了,html2canvas 就是一個關注度很高的 js 截屏庫,它考慮的內容會更多更全面。比如:

我博客左側的微博小圖標,hover 上去有一個微博分享,這里我就使用了這個庫截取博客全文視圖(考慮小屏手機,我把寬度設置成 480,比較窄),其實現是很簡單的:

html2canvas(document.body).then(function(canvas) {
   canvas.id = 'screenshotCanvas';
   document.body.appendChild(canvas);
});

此時,頁面的截圖已經 append 到了 body 中。canvas 提供了導出圖片的函數:

var can = documeng.getElementById("screenshotCanvas");
var imgDataURI = can.toDataURL('image/png');

我們也可以將到處的內容轉化成一個 blob 流,這樣就能直接通過 URI 地址來訪問了。

無論是 dataURI 還是還是 blob 流,他們都沒辦法當做一個 URL 在網絡上訪問,所以當我使用微博分享(附加圖片分享)的時候,圖片總是拿不到。

var shareUrl = "http://service.weibo.com/share/share.php?appkey=YOUR_APP_KEY&title=" 
    + title + "&url=" + url + "&searchPic=false&style=simple&pic=" 
    + picUrl;

這里的 picUrl 必須是一個 http 可請求到的地址,實在是無奈呀,在 coding.net 寫了一個小應用,用來臨時儲存圖片(10分鍾之后刪除上傳圖片),有需要的可以試用下:

JQuery 用戶可以這樣搞:

var fd = new FormData();
fd.append("img", imgBlob);
$.ajax({
  type: "POST",
  url: "http://tmpfile.coding.io/img",
  dataType: 'json',
  data: fd,
  crossDomain: true,
  processData: false,
  contentType: false,
  success: function(data){
    if(data && data.path) {    
      console.log("http://tmpfile.coding.io/tmp" + data.path);
    }
  }
});

只要能拿到原始圖,之后的加工處理都是比較簡單的。比如如何實現畫框截取某個區域的圖形,思路就是截取整圖,記住鼠標按下和抬起的兩個點,然后從整圖中摳出來就搞定了。在 QQ 空間發表說說的地方有提供截屏工具,這是因為騰訊在電腦上安裝了插件,並且提供了對應的 JS 接口,JS 是沒有能力直接截屏的。

好吧,了解原理就好,人家有現成的庫可以用,咱們不要動不動就造輪子,不好玩。

引用https://www.barretlee.com/blog/2015/09/24/screenshot-with-javascript/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM