2013-07-08 76 views
3

我想通過使用scrollTo移動窗口並在彈出窗口的畫布上拼接圖像來製作截取整個頁面的屏幕截圖。但是,我的問題是,所有的圖像回來都沒有被繪製/不顯示在畫布上。鉻擴展畫布不在循環內繪製圖像

popup.js

function draw(ctx, image, x ,y) { 
    console.log(image); 
    var img = new Image(); 
    img.src = image; 
    img.onload = function() { 
    ctx.drawImage(img, x, y); 
    console.log('x',x); 
    console.log('y',y); 
    }; 
} 

function screenshot(response) { 
    console.log('screenshot'); 
    var canvas = document.getElementById('imagecanvas'), 
    fullHeight = response.height, 
    fullWidth = response.width, 
    visibleHeight = response.visibleHeight, 
    visibleWidth = response.visibleWidth, 
    x = 0, 
    y = 0; 

    canvas.height = fullHeight; 
    canvas.width = fullWidth; 

    var ctx = canvas.getContext('2d'); 
    // console.log('canvas', canvas); 
    // console.log('context', ctx); 
    //start at the top 
    window.scrollTo(0, 0); 

    while (y <= fullHeight) { 
    chrome.tabs.captureVisibleTab(null, { 
     format: 'png' 
    }, function (image) { 
     draw(ctx, image, x, y); 
    }); 

    // console.log('x',x); 
    // console.log('y',y); 

    y += visibleHeight; 
    window.scrollTo(x, y); 
    } 
} 

chrome.tabs.query({ 
    'active': true, 
    'currentWindow':true 
}, function(tab){ 
    console.log('sending message'); 
    chrome.tabs.sendMessage(tab[0].id, { 
    message: 'dom' 
    }, function(response){ 
    console.log('response', response); 
    screenshot(response); 
    }); 
}); 

popup.html

<!doctype html> 
<html> 
    <head> 
    <title>Chrome Snapshot</title> 
    <style> 
    #imagecanvas { 
     z-index: 100; 
    } 
    </style> 
    <script src="jquery-2.0.2.min.js"></script> 
    <script src="popup.js"></script> 
    </head> 
    <body> 
    <canvas id="imagecanvas"> </canvas> 
    </body> 
</html> 

content.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) { 
    if (request.message === 'dom') { 
     sendResponse({ 
     height:   document.height, 
     width:   document.width, 
     visibleHeight: window.innerHeight, 
     visibleWidth: window.innerWidth 
     }); 
    } 
    }); 

的manifest.json

{ 
    "manifest_version": 2, 
    "name": "test", 
    "description": "Save images and screenshots of sites to Dropbox.", 
    "version": "1.0", 
    "permissions": [ 
    "<all_urls>", 
    "tabs" 
    ], 
    "browser_action": { 
    "default_icon": "icon.png", 
    "default_popup": "popup.html" 
    }, 
    "background": { 
    "scripts": [ 
     "jquery-2.0.2.min.js" 
    ], 
    "persistent": false 
    }, 
    "content_scripts" : [{ 
    "all_frames": true, 
    "matches" : ["*://*/*"], 
    "js" : ["content.js"], 
    "run_at": "document_end" 
    }] 
} 

編輯迴應羅布的評論

繼承人是我迄今爲止:我可以看到被滾動的頁面,但現在,從captureVisibleTab圖像返回爲未定義。

popup.js

var ctx, 
    fullHeight, 
    fullWidth, 
    x, 
    y, 
    visibleHeight, 
    visibleWidth; 

function draw(ctx, image, x ,y) { 
    console.log(image); 
    var img = new Image(); 
    img.src = image; 

    img.onload = function() { 
    ctx.drawImage(img, x, y); 
    // console.log('x',x); 
    // console.log('y',y); 
    }; 
} 

function next(tabID) { 
    chrome.tabs.captureVisibleTab(null, { 
    format: 'png' 
    }, function(image) { 
    console.log(image); 
    draw(ctx, image, x, y); 
    y += visibleHeight; 

    if (y < fullHeight) { 
     chrome.tabs.sendMessage(tabID, { 
      message: 'scroll', 
      x: x, 
      y: y 
     }, function() { 
     next(tabID); 
     }); 
    } 
    }); 
} 

function screenshot(response, tabID) { 
    console.log('screenshot'); 
    var canvas = document.getElementById('imagecanvas'); 

    fullHeight = response.height; 
    fullWidth = response.width; 

    visibleHeight = response.visibleHeight, 
    visibleWidth = response.visibleWidth; 

    x = 0, 
    y = 0; 

    canvas.height = fullHeight; 
    canvas.width = fullWidth; 

    ctx = canvas.getContext('2d'); 

    chrome.tabs.sendMessage(tabID, { 
     message: 'scroll', 
     x: x, 
     y: y 
    }, function() { 
     next(tabID); 
    }); 
} 

chrome.tabs.query({ 
    active:true, 
    lastFocusedWindow:true 
}, function(tab){ 
    var tabID = tab[0].id; 
    console.log('sending message', tabID); 
    chrome.tabs.sendMessage(tabID, { 
    message: 'dom' 
    }, function(response){ 
    console.log('dom info', response); 
    screenshot(response, tabID); 
    }); 
}); 

content.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) { 
    if (request.message === 'dom') { 
     sendResponse({ 
     height:   document.height, 
     width:   document.width, 
     visibleHeight: window.innerHeight, 
     visibleWidth: window.innerWidth 
     }); 
    } else if (request.message == 'scroll') { 
     window.scrollTo(request.x, request.y); 
     sendResponse(); 
    } 
    }); 
+1

嘗試'文檔。createElement('img');'而不是'new Image();'。在Image構造函數的實現中存在一個錯誤 - 請參閱[http://crbug.com/245296](https://code.google.com/p/chromium/issues/detail?id=245296「調用新選項( ),新的圖像(),新的音頻()在一個頁面的DOM構造函數在內容腳本無效相同的構造函數(反之亦然)「) –

+0

沒有解決不了 – Raptrex

回答

3

您的代碼有兩個顯著的​​問題。

第一個問題是,你認爲window.scrollTo(0, 0);滾動標籤的內容。這不是真的,它會滾動彈出窗口的文檔。

第二個問題是您在循環中調用異步方法,該循環在每次迭代中都會更改y變量。在這個captureVisibleTab的回調中,您再次讀取y變量,但由於在循環結束時調用所有回調函數,所以它始終是相同的值。

順便說一下,這個值也是錯誤的。你正在循環,直到y <= fullHeight。這實際上應該是y < fullHeight,因爲一旦你到達頁面底部,就不需要再拍一張截圖了。

至少,您需要將您的循環更改爲(遞歸)一組回調。

// popup.js 
    function next() { 
    chrome.tabs.captureVisibleTab(null, { 
     format: 'png' 
    }, function (image) { 
     draw(ctx, image, x, y); 
     y += visibleHeight; 

     window.scrollTo(x, y); // TODO 
     next(); 
    }); 
    } 
    // Initialize recursion 
    next(); 

這種方法要稍微好一些,至少你看到被畫在畫布上的東西。但它仍然不正確,因爲您仍然在彈出的腳本中調用window.scrollTo。解決此問題的正確方法是將scrollTo方法委託給內容腳本,並使用message passing來調用滾動。例如:

// popup.js 
     //window.scrollTo(x, y); // TODO 
     //next(); 
     chrome.tabs.sendMessage(null, { 
      request: 'scroll', 
      x: x, 
      y: y 
     }, next); 

// contentscript.js 
chrome.runtime.onMessage.addListener(function(message, sender,sendResponse) { 
    if (message.request == 'scroll') { 
     window.scrollTo(message.x, message.y); 
     sendResponse(); 
    } 
}); 

最後一個建議:不要將所有選項卡插入內容腳本,我建議使用activeTab permissionchrome.tabs.executeScript需要時插入內容腳本。這使得您的擴展程序更輕,並且不需要<all_urls>權限。

+0

我將如何發送消息沒有標籤ID當我使用activeTabs?使用null作爲tabid不起作用https://gist.github.com/raptrex/5982555 – Raptrex

+0

@Raptrex ['chrome.browserAction.onClicked'](https://developer.chrome.com/extensions/browserAction.html #event-onClicked)事件接收到一個'Tab'類型的參數,它將ID作爲'id'屬性提供。 –

+0

無法使用browserAction.onClicked,因爲:'點擊瀏覽器操作圖標時觸發。如果瀏覽器操作有彈出窗口,則該事件不會觸發。# – Raptrex