2013-07-08 58 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