2016-09-09 16 views
0

この描画アプリケーションは、私のラップトップで完全に機能しました。異なる画面サイズでテストすると、描画された線がカーソルと揃っていません。スケーリングの仕組みをいくつか適用しなければならないと思います。HTMLキャンバス描画アプリケーションが別の画面サイズで破損する

// DRAWING FUNCTIONALITY 
var canvas, ctx, painting = false, 
    previousMousePos; 

    function getMousePos(canvas, evt) { 
    var rect = canvas.getBoundingClientRect(); 
    return { 
     x: evt.clientX - rect.left, 
     y: evt.clientY - rect.top 
    } 
    }; 
    // Sender drawing function. 
    function drawLineImmed(x1, y1, x2, y2) { 
    ctx.beginPath(); 
    ctx.moveTo(x1, y1); 
    ctx.lineTo(x2, y2); 
    ctx.strokeStyle = 'white'; 
    ctx.stroke(); 
    }; 
    // Receiver drawing function. 
    function drawLineTwo(data) { 
    ctx.beginPath(); 
    ctx.moveTo(data.px, data.py); 
    ctx.lineTo(data.mx, data.my); 
    ctx.strokeStyle = 'white'; 
    ctx.stroke(); 
    }; 
    // Get draw data. Pass to receiver drawing function. 
    socket.on('draw', function(data) { 
    drawLineTwo(data); 
    }); 
    // Sender emit drawing data. 
    function mouseMove(evt) { 
    var mousePos = getMousePos(canvas, evt); 
    if (painting) { 
     drawLineImmed(previousMousePos.x, previousMousePos.y, mousePos.x, mousePos.y); 
     socket.emit('draw', {px:previousMousePos.x, py:previousMousePos.y, mx:mousePos.x, my:mousePos.y}, page); 
     previousMousePos = mousePos; 
    }; 
    }; 
    function clicked(evt) { 
    previousMousePos = getMousePos(canvas, evt); 
    painting = true; 
    }; 
    function release(evt) { 
    painting = false; 
    }; 
    function leave(evt) { 
    painting = false; 
    }; 
    $(document).ready(function() { 
    canvas = document.getElementById('canvas'); 
    ctx = canvas.getContext('2d'); 
    painting = false; 
    canvas.addEventListener('mousemove', mouseMove, false); 
    canvas.addEventListener('mousedown', clicked); 
    canvas.addEventListener('mouseup', release); 
    canvas.addEventListener('mouseleave', leave); 
    }); 

// CSS何相対的な縮尺としたもの

#canvas { 
    border-radius: 2px; 
    background-color: rgb(33,37,43); 
    position: fixed; 
    left: 1.7%; 
    top: 3%; 
    border-radius: 8px; 
    border-style: solid; 
    border-width: 3px; 
    border-color: black; 
    width: 80%; 
} 

+0

同じブラウザとバージョンが一致しない場合はどうなりますか? –

+0

はい、この場合でも –

+0

が便利です:http://stackoverflow.com/a/35741551/128511 – gman

答えて

0

にこの回答を参照してください。キャンバス内にあるピクセル数(canvas.width & canvas.height)を定義するサイズとCSSによって設定されるキャンバスのサイズが表示されます。

私はサイズを変更する通常の方法は、その後、私は(例えばmouseMoveイベントにすることができる)描画する前に、その呼び出し、このよう

function resizeCanvasToMatchDisplaySize(canvas) { 

    // look up the size the canvas is displayed 
    var desiredWidth = canvas.clientWidth; 
    var desiredHeight = canvas.clientHeight; 

    // if the number of pixels in the canvas doesn't match 
    // update the canvas's content size. 
    if (canvas.width != desiredWidth || canvas.height != desiredHeight) { 
    canvas.width = desiredWidth; 
    canvas.height = desiredHeight; 
    } 
} 

です。その方法では、サイズが変更された場合にのみキャンバスをクリアします。

また、canvas.getBoundingClientRect()it is technically more correctを使用することもできますが、通常は自分の目的に合わないゴミも生成されます。あなたのためには、私はそれが問題ではないと思う。

いつでもキャンバスのサイズを設定/変更すると、そのすべてについてリセットされ、クリアされます。つまり、fillStyle,lineWidthなどの設定は、サイズを変更するとすべてデフォルトにリセットされます。過去のサイズ変更をしたい場合は、何とか記録する必要があります。アイデアには、これまでに描画されたすべてのものを追跡し、サイズ変更後に再び描画することが含まれます。古いキャンバスのサイズが大きかったあなたがコンテンツをクリッピング終わるつもりならもう一つのアイデアはもちろん

// make a new canvas if we haven't already 
offscreenCanvas = offscreenCanvas || document.createElement("canvas"); 

// make the offscreen canvas match the size of the onscreen canvas 
offscreenCanvas.width = onscreenCanvas.width; 
offscreenCanvas.height = onscreenCanvas.height; 

// get a context for a offscreen canvas 
offscreenCanvasContext = offscreenCanvas.getContext("2d"); 

// clear it just in case it's old and the size didn't change. 
offscreenCanvasContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height); 

// copy the onscreen canvas to the offscreen canvas 
offscreenCanvasContext.drawImage(onscreenCanvas, 0, 0); 

// resize the onscreen canvas 
reiszeCanvasToMatchDisplaySize(onscreenCanvas); 

// copy back the old content 
onscreenCanvasContext.drawImage(offscreenCanvas, 0, 0); 

// free the memory used by the offscreen canvas 
offscreenCanvas.width = 0; 
offscreenCanvas.height = 0; 

のようなものを使用して別のオフスクリーンキャンバスに現在のキャンバスをコピーすることです。また

キャンバスのdrawingBufferサイズ(画素数)表示サイズyou can do the math to make the mouse position still match

+0

わかりました。私はcanvas.widthとcanvas.clientWidthの違いを理解していませんでした。このコードは非常に直感的です。良い仕事、ありがとう。 –

1

キャンバス表示サイズはスタイル属性で設定され、キャンバス解像度と同じではありません。表示サイズに合わせてキャンバス解像度を設定していることを示すコードが表示されない場合は、アスペクトとサイズを変更すると問題が発生します。

キャンバスを取得すると、境界ボックスが表示され、その解像度が表示ピクセルサイズに一致するように設定されます。キャンバスは2つのサイズを持つBlindman67が指摘するように

var rect = canvas.getBoundingClientRect(); 
canvas.width = rect.width; 
canvas.height = rect.height; 

は、詳細情報については、関連する質問Fullscreen canvas

+0

キャンバス解像度と表示サイズを一致させることができませんでした。あなたの提案にマッチするようにコードを編集しました。私は、小さな線がカーソルに沿って完全に追跡していることを発見しています。しかし、新しい問題があります。カーソルがキャンバス上を移動すると、描画された線が削除されます。私のカーソルの後ろの行は、描画された直後に削除されますが、後ろに1センチの行しか表示されません。描画された線はsocket.ioを使ってクライアントに送信されますが、そのユーザーがキャンバス上にマウスを置くと線が削除されます。あなたはなにか考えはありますか? –

+1

サイズを設定すると、その行は削除されます。削除したくない場合は、すべての行を記録し、サイズを変更した後に再描画する必要があります。 – gman

+0

getMousePos()のほかにキャンバスの幅と高さを設定することはできますか?そうすれば、マウスを動かすたびにリセットされません。たとえば、キャンバスのイベントリスナーで設定すると機能しません。線はうまく描きますが、私のカーソルには追従しません。 1ページに1回だけこれを設定する必要はありませんか? –

関連する問題