canvas - chrome扩展 Canvas 不在循环内绘制图像

标签 canvas google-chrome-extension html5-canvas

我正在尝试制作一个屏幕截图扩展,通过使用scrollTo移动窗口并在弹出窗口中将 Canvas 上的图像拼接在一起来截取整个页面的屏幕截图。然而,我的问题是,我返回的所有图像都没有被绘制/没有显示在 Canvas 上。

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

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

最佳答案

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

第一个问题是您假设 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();

这个方法稍微好一点,至少你看到 Canvas 上正在画东西。但这仍然不正确,因为您仍在调用 window.scrollTo在弹出脚本中。解决此问题的正确方法是委托(delegate) 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>许可。

关于canvas - chrome扩展 Canvas 不在循环内绘制图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17519325/

相关文章:

javascript - HTML5 Canvas - 添加更多圆圈以圆周运动旋转

java - 在 Canvas 上展示广告

css - EaselJs:如何限制 Canvas 内的图像移动(缩放或旋转后)?

javascript - 检测Flash播放器当前是否正在播放? - Chrome 扩展

google-chrome-extension - YouTube 视频的 getCurrentTime()

javascript - 在javascript中减少维持宽高比的base64图像的尺寸

javascript - webglcontextcreationerror 事件 : is it triggered synchronously?

javascript - Chrome 扩展 addListener 无法发送响应,因为端口为空

javascript - 如何让球从 Canvas 上水平弹起

javascript - 为什么canvas和webgl渲染器不一样? (三.js)