Javascript 画布绘制函数以异步方式运行
我在这里所做的是用画布层覆盖整个网页。现在,用户在画布上单击,然后单击创建一个点。此时将调用Javascript 画布绘制函数以异步方式运行,javascript,jquery,html,google-chrome-extension,html5-canvas,Javascript,Jquery,Html,Google Chrome Extension,Html5 Canvas,我在这里所做的是用画布层覆盖整个网页。现在,用户在画布上单击,然后单击创建一个点。此时将调用createDot()函数 在createDot()内部,点被绘制到画布上,然后屏幕截图请求被发送到后台脚本 现在的问题是,当我点击画布并拍摄截图时,这个点并没有出现在截图中 奇怪的是,当我在同一张画布上点击第二个点时,当屏幕截图出现时,它现在有了我点击的第一个点,但没有第二个点。 所以现在的情况是,屏幕截图并没有捕捉到当前的点,而只是捕捉到了之前的点 我检查了canvas绘图函数是否都处于阻塞状态,以便
createDot()
函数
在createDot()
内部,点被绘制到画布上,然后屏幕截图请求被发送到后台脚本
现在的问题是,当我点击画布并拍摄截图时,这个点并没有出现在截图中
奇怪的是,当我在同一张画布上点击第二个点时,当屏幕截图出现时,它现在有了我点击的第一个点,但没有第二个点。
所以现在的情况是,屏幕截图并没有捕捉到当前的点,而只是捕捉到了之前的点
我检查了canvas绘图函数是否都处于阻塞状态,以便在绘图完成之前无法将请求发送到后台脚本。我还通过登录控制台确认了这一点
内容脚本:
function createDot(canvas) {
var context = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var pointX , pointY;
var point_X,point_Y;
function handleMouseDown(e) {
//coordinates of the click in dom.
pointX = parseInt(e.pageX - offsetX);
pointY = parseInt(e.pageY - offsetY);
//making the dot
var radius = 10;
context.beginPath();
context.arc(pointX, pointY, radius, 0, 2 * Math.PI);
context.fillStyle = 'red';
context.fill();
context.lineWidth = 2;
context.strokeStyle = '#003300';
context.stroke();
console.log("drawn everything");
takeDotScreenshot(); //gets called when the canvas has finished its job of drawing.
}
$("#canvas").mousedown(function (e) {
handleMouseDown(e);
});
}
function takeDotScreenshot() {
console.log("sending request to Background script");
chrome.runtime.sendMessage({"capture":true},function(response) {
var img_src=response.screenshot;
});
//logic for using that screenshot and appending it on to the content page...
}
背景脚本:
chrome.runtime.onMessage.addListener(function(request,sender,sendResponse) {
if(request.capture) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.captureVisibleTab(null, {}, function(dataUrl) {
if(dataUrl) {
sendResponse({"screenshot":dataUrl});
}
});
});
}
return true;
});
更新:
如果我使用setTimeout 1ms调用takeDotScreenshot函数,一切正常。为什么
setTimeout(takeDotScreenshot, 1);
屏幕快照是用户可以看到的内容的快照。在呈现函数内部时,画布不会显示,直到执行堆栈为空(从函数中返回) 根据渲染方式(使用requestAnimationFrame或直接从鼠标、键盘、计时器事件)画布仍需要时间才能显示 将超时设置为零时,可以将调用添加到调用堆栈中,该调用堆栈在画布显示之前运行。您运行的任何代码都会阻塞页面,从而阻止画布显示,因此没有屏幕截图
我会设置从渲染到捕获的超时时间至少为17ms(刚好超过60fps)。没有人会注意到延迟,但会给画布足够的时间显示在屏幕上屏幕快照是用户可以看到的内容的快照。在呈现函数内部时,画布不会显示,直到执行堆栈为空(从函数中返回) 根据渲染方式(使用requestAnimationFrame或直接从鼠标、键盘、计时器事件)画布仍需要时间才能显示 将超时设置为零时,可以将调用添加到调用堆栈中,该调用堆栈在画布显示之前运行。您运行的任何代码都会阻塞页面,从而阻止画布显示,因此没有屏幕截图
我会设置从渲染到捕获的超时时间至少为17ms(刚好超过60fps)。没有人会注意到这种延迟,但却给了画布足够的时间显示在屏幕上有一个非常详细、非常好的答案,为什么setTimeout在这里有帮助:
画布的DOM更新事件(实际上使点可见)可能在您的截图事件之后,即使画布从stroke()事件接收到所需的所有数据。这里有一个非常详细、非常好的答案,为什么setTimeout有帮助:
画布的DOM更新事件(实际上使圆点可见)可能在take screenshot事件之后,即使画布从stroke()事件接收到所需的所有数据。@wOxxOm我尝试了零,但它不起作用,当我设置1毫秒的延迟时,它会运行。我仍然不明白为什么会发生这种情况。可能是@wOxxOm的重复。我尝试了零,但它不起作用,当我将延迟设置为1ms时,它会运行。我仍然不明白为什么会发生这种情况。可能是重复的