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>

内容.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"
  }]
}

编辑以回应 Rob 的评论

这是我到目前为止所拥有的:我可以看到正在滚动的页面,但是现在,来自 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);
  });
});

内容.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

您的代码有两个重要问题。

第一个问题是您假设window.scrollTo(0, 0);滚动选项卡的内容。这不是真的,它会滚动弹出窗口的文档。

第二个问题是您在循环中调用异步方法,该方法会y在每次迭代时更改变量。在 this 的回调中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方法委托给内容脚本,并使用消息传递来调用滚动。例如:

// 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 权限chrome.tabs.executeScript在需要时插入内容脚本。这使您的扩展不那么繁重,并消除了对<all_urls>许可的需要。

于 2013-07-11T09:50:02.967 回答