Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 画布绘制函数以异步方式运行_Javascript_Jquery_Html_Google Chrome Extension_Html5 Canvas - Fatal编程技术网

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时,它会运行。我仍然不明白为什么会发生这种情况。可能是重复的