1

私がここでやっていることは、キャンバスのレイヤーがロードされたWebページ全体をカバーしていることです。そのキャンバス上でユーザーがクリックすると、そのクリックが点を作成します。その時点でcreateDot()関数が呼び出されます。キャンバスの描画関数が非同期で動作する

createDot()の中にドットがキャンバスに描画され、スクリーンショット要求がバックグラウンドスクリプトに送信されます。

ここで問題になるのは、キャンバスをクリックしてスクリーンショットを撮ると、スクリーンショットにドットが表示されないということです。

今、私は同じキャンバスに2番目のドットをクリックすると、スクリーンショットが来ると、それは今クリックしたが2番目のものではない最初のドットになります。

だから、スクリーンショットでは現在のドットはキャプチャされず、以前のドットだけがキャプチャされているということです。

キャンバス描画関数がすべてブロックされているため、描画が完了する前にバックグラウンドスクリプトにリクエストを送信できないことを確認しました。私はまた、コンソールにログインして同じことを確認しました。

コンテンツスクリプト:

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

UPDATE:

私はtakeDotScreenshot機能を呼び出すための1ミリ秒のsetTimeoutメソッドを使用している場合は、すべてが正常に動作します。なぜ!

setTimeout(takeDotScreenshot, 1); 
+0

@wOxxOm私はゼロを試しましたが、動作しません。なぜこれが起こっているのかまだ分かりません。 –

+1

[なぜsetTimeout(fn、0)が便利なのはなぜですか?](http://stackoverflow.com/questions/779379/why-is-settimeoutoutfn-0-sometimes-useful) – wOxxOm

答えて

0

スクリーンショットは、ユーザーが見ることのできるスナップショットです。レンダリング関数の内部では、実行スタックが空になるまで(関数の途中から返されるまで)、キャンバスは表示されません。requestAnimationFrameを使用するか、マウス、キーボード、タイマーイベントから直接レンダリングする方法に応じて、キャンバスはディスプレイに表示されるまでにまだ時間がかかります。

タイムアウトをゼロに設定すると、キャンバスがディスプレイに表示される前に実行されるコールスタックにコールを追加できます。実行するコードによってページがブロックされ、キャンバスが表示されず、スクリーンショットが表示されなくなります。

レンダリングからタイムアウトを少なくとも17ms(ちょうど60fps以上)に設定します。誰もその遅延に気付くことができますが、キャンバスがディスプレイに表示されるのに十分な時間を与えます。

関連する問題