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
      });
    }
  });

マニフェスト.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();
    }
  });
4

1 に答える 1

3

コードには 2 つの重大な問題があります。

window.scrollTo(0, 0);最初の問題は、 がタブのコンテンツをスクロールすると仮定していることです。これは正しくありません。ポップアップのドキュメントをスクロールします。

y2 番目の問題は、反復ごとに変数を変更するループ内で非同期メソッドを呼び出していることです。this のコールバックでは、再度変数をcaptureVisibleTab読み込んでいyますが、ループが終了するとすべてのコールバックが呼び出されるため、常に同じ値になります。

ちなみに、この値も間違っています。までループしていますy <= fullHeighty < 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メソッドをコンテンツ スクリプトに委譲し、メッセージ パッシングを使用してスクロールを呼び出すことです。例えば:

// 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();
    }
});

最後に 1 つの提案: すべてのタブにコンテンツ スクリプトを挿入する代わりに、activeTab パーミッションを使用し、chrome.tabs.executeScript必要に応じてコンテンツ スクリプトを挿入することをお勧めします。<all_urls>これにより、拡張機能が軽くなり、パーミッションが不要になります。

于 2013-07-11T09:50:02.967 に答える