2013-07-08 3 views
3

Я пытаюсь сделать снимок экрана, который снимает скриншот всей страницы, перемещая окно с помощью scrollTo и сшивая изображения вместе на холсте во всплывающем окне. Тем не менее, моя проблема заключается в том, что все образы im, возвращающиеся назад, не выводятся/не отображаются на холсте.chrome extention canvas not drawing images внутри цикла

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 «Вызов нового параметра (), новый Image(), новый конструктор DOM() 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 permission и chrome.tabs.executeScript, чтобы вставить скрипт контента, когда это необходимо. Это делает ваше расширение менее тяжелым и устраняет необходимость в разрешении <all_urls>.

+0

как отправить сообщение без идентификатора табуляции когда я использую 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'. –

+0

Невозможно использовать browserAction.onClicked, потому что: 'Вызывается, когда нажимается значок действия браузера. Это событие не будет срабатывать, если действие браузера имеет всплывающее окно. – Raptrex