画布绘制函数以异步方式运行
Canvas drawing functions behaving in asynchronous way
我在这里做的是覆盖整个网页,加载了画布层。现在,在该画布上,用户单击该单击将创建一个点。此时createDot()
函数被调用。
在createDot()
内部,点被绘制到画布上,然后将屏幕截图请求发送到后台脚本。
现在的问题是,当我单击画布并截取屏幕截图时,屏幕截图中没有出现该点。
现在奇怪的是,当我在同一画布上单击第二个点并且屏幕截图出现时,它现在有我单击的第一个点,而不是第二个点。
因此,正在发生的事情是屏幕截图没有捕获当前点,而只是捕获以前的点。
我检查了画布绘图功能是否全部阻塞,因此在绘图完成之前无法将请求发送到后台脚本。我也通过登录到控制台来确认这一点。
内容脚本:
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);
有一个非常详细,很好的答案,为什么setTimeout在这里有帮助:https://stackoverflow.com/a/4575011/10574621
画布的 DOM-Update-事件(实际上使点可见)可能位于截图事件后面,即使画布从 stroke() 事件中接收到所需的所有数据也是如此。
屏幕截图是用户可以看到的内容的快照。在呈现函数中时,画布不会显示,直到执行堆栈为空(从函数中一直返回)
根据渲染方式(使用 requestAnimationFrame 或直接从鼠标、键盘、计时器事件),画布仍需要一些时间才能呈现给显示器。
将超时设置为零时,可以将调用添加到在画布呈现给显示器之前运行的调用堆栈。您运行的任何代码都将阻止页面,从而阻止显示画布,从而没有屏幕截图。
我会将渲染的超时设置为捕获至少 17 毫秒(略高于 60fps)。没有人能注意到这种延迟,但有足够的时间将画布呈现给显示器
- 如何以异步方式打印q中的项目
- 我想以异步方式执行常规函数
- 在Nodejs中堆叠异步回调事件的最佳方式
- 节点.js:如何以编程方式确定异步
- 网页异步更新的方式有哪些
- 接收json异步响应的最有效方式
- 以编程方式将同步代码转换为异步代码
- Javascript:调整base64图像的大小并以非异步方式返回字符串
- 什么's是在Node.js中链接异步函数的正确方式
- Node.js:执行多个异步操作的最佳方式,然后执行其他操作
- 在NodeJ中执行异步卷曲的最佳方式
- 如果以异步方式加载绑定的资源,则函数中的$watch/$timeout包装会中断双向绑定
- 优雅的方式运行大量异步“;事物;当总数为'直到第一个“;事物;退货
- 以异步方式向前端web应用程序添加设置文件
- 如何以组的方式调用一个异步函数?
- 通过Promises异步加载外部js文件的最佳方式
- 异步加载下划线模板的最佳方式
- 以事件驱动的方式编写异步代码
- 以异步方式设置函数参数
- 画布绘制函数以异步方式运行