使用 JavaScript 截屏

常常在微博上看到不少內容使用的什麼長微博截圖,而且截圖上還附加了不少其餘的信息。以前對純前端截圖有些研究,正好本博客有這個需求,今天就把這東西實現了下。javascript

須要聲明的是,JavaScript 目前還不能實現網頁截屏,就算之後可以實現,也必定是瀏覽器提供了相關接口,JS 去調用這些接口。既然不能截屏,那咱們能作的只有經過拿到像素點的信息來」拼湊」圖片。php

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

// 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 以後執行下上面的文件:html

phantomjs render.js

你會發現,一張寬度很窄的淘寶首頁圖就保存到了同目錄下的 taobao_home.jpeg 中。也有同窗使用 phantomjs 作了不少有意思的東西,好比每隔 100ms 截圖,而後對比圖像之間的差別,分析網頁的加載狀況和性能問題,甚至作網頁的監控。好吧,話題收回來,繼續說說其餘的截屏方式,關於 phantomjs 能夠移步到官網學習。前端

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

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

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

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

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

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

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

咱們也能夠將處處的內容轉化成一個 blob 流,這樣就能直接經過 URI 地址來訪問了。ajax

不管是 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/

相關文章
相關標籤/搜索