Posizione reale del mouse su canvas

Sto provando a disegnare con il mouse su una canvas HTML5, ma l’unico modo in cui sembra funzionare bene è se la canvas si trova nella posizione 0,0 (angolo superiore sinistro) se cambio la posizione della canvas, per qualche motivo non disegna come dovrebbe Ecco il mio codice.

function createImageOnCanvas(imageId){ document.getElementById("imgCanvas").style.display = "block"; document.getElementById("images").style.overflowY= "hidden"; var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); var img = new Image(300,300); img.src = document.getElementById(imageId).src; context.drawImage(img, (0),(0)); } function draw(e){ var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); posx = e.clientX; posy = e.clientY; context.fillStyle = "#000000"; context.fillRect (posx, posy, 4, 4); } 

La parte HTML

   

Ho letto che c’è un modo di creare una semplice funzione in JavaScript per ottenere la giusta posizione, ma non ho idea di come farlo.

Lo scenario 1: 1 semplice

Per le situazioni in cui l’elemento canvas è 1: 1 rispetto alla dimensione bitmap, puoi ottenere le posizioni del mouse usando questo snippet:

 function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: evt.clientX - rect.left, y: evt.clientY - rect.top }; } 

Chiamalo dal tuo evento con l’evento e canvas come argomenti. Restituisce un object con xey per le posizioni del mouse.

Dato che la posizione del mouse che stai ottenendo è relativa alla finestra del client, devi sottrarre la posizione dell’elemento canvas per convertirlo rispetto all’elemento stesso.

Esempio di integrazione nel tuo codice:

 //put this outside the event loop.. var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); function draw(evt) { var pos = getMousePos(canvas, evt); context.fillStyle = "#000000"; context.fillRect (pos.x, pos.y, 4, 4); } 

Fiddle con modifiche

Nota: i bordi e il padding influenzeranno la posizione se applicati direttamente all’elemento canvas, quindi questi devono essere considerati tramite getComputedStyle() oppure applicare tali stili a una div principale.

Quando Element e Bitmap hanno dimensioni diverse

Quando c’è la situazione di avere l’elemento in una dimensione diversa rispetto alla bitmap stessa, ad esempio, l’elemento viene ridimensionato usando CSS o ci sono pixel-aspect ratio ecc. Dovrai affrontare questo.

Esempio:

 function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(), // abs. size of element scaleX = canvas.width / rect.width, // relationship bitmap vs. element for X scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y return { x: (evt.clientX - rect.left) * scaleX, // scale mouse coordinates after they have y: (evt.clientY - rect.top) * scaleY // been adjusted to be relative to element } } 

Fiddle usando la scala

Con le trasformazioni applicate al contesto (scala, rotazione ecc.)

Poi c’è il caso più complicato in cui è stata applicata la trasformazione al contesto come rotazione, inclinazione / inclinazione, scala, traslazione, ecc. Per affrontarlo è ansible calcolare la matrice inversa della matrice corrente.

I browser più recenti consentono di leggere la matrice corrente tramite la proprietà currentTransform e Firefox (alfa corrente) forniscono anche una matrice invertita attraverso il mozCurrentTransformInverted . Firefox tuttavia, tramite mozCurrentTransform , restituirà una matrice e non DOMMatrix come dovrebbe. Né Chrome, quando abilitato tramite flag sperimentali, restituirà un DOMMatrix ma una SVGMatrix .

Nella maggior parte dei casi, tuttavia, dovrai implementare una soluzione personalizzata per matrici (come la mia soluzione qui – progetto gratuito / MIT) fino a quando non avrai pieno supporto.

Quando alla fine hai ottenuto la matrice indipendentemente dal percorso che prendi per ottenerne una, devi invertirla e applicarla alle coordinate del tuo mouse. Le coordinate vengono quindi passate all’area di disegno che utilizzerà la sua matrice per convertirla in qualsiasi posizione al momento.

In questo modo il punto sarà nella posizione corretta rispetto al mouse. Anche qui è necessario regolare le coordinate (prima di applicare la matrice inversa ad esse) per essere relative all’elemento.

Un esempio che mostra solo i passaggi della matrice

 function draw(evt) { var pos = getMousePos(canvas, evt); // get adjusted coordinates as above var imatrix = matrix.inverse(); // get inverted matrix somehow pos = imatrix.applyToPoint(pos.x, pos.y); // apply to adjusted coordinate context.fillStyle = "#000000"; context.fillRect(pos.x-1, pos.y-1, 2, 2); } 

Esempio utilizzando la soluzione collegata sopra (sostituirla con una soluzione browser nativa quando più ampiamente supportata).

Un esempio di utilizzo di currentTransform quando implementato sarebbe:

  var pos = getMousePos(canvas, e); // get adjusted coordinates as above var matrix = ctx.currentTransform; // W3C (future) var imatrix = matrix.invertSelf(); // invert // apply to point: var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e; var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f; 

Aggiornamento Ho creato una soluzione gratuita (MIT) per incorporare tutti questi passaggi in un singolo object facile da usare che può essere trovato qui e che si occupa anche di alcune altre cose meno importanti.

Puoi ottenere le posizioni del mouse usando questo snippet:

 function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: (evt.clientX - rect.left) / (rect.right - rect.left) * canvas.width, y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * canvas.height }; } 

Questo codice prende in considerazione sia la modifica delle coordinate nello spazio su canvas ( evt.clientX - rect.left ) che il ridimensionamento quando le dimensioni logiche del canvas differiscono dalle dimensioni dello stile ( / (rect.right - rect.left) * canvas.width see: Canvas width e altezza in HTML5 ).

Esempio: http://jsfiddle.net/sierawski/4xezb7nL/

Fonte: commento jerryj su http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/

È necessario ottenere la posizione del mouse relativa alla canvas

Per fare ciò è necessario conoscere la posizione X / Y della canvas sulla pagina.

Questo è chiamato “offset” della canvas, ed ecco come ottenere l’offset. (Sto usando jQuery per semplificare la compatibilità cross-browser, ma se vuoi usare javascript non elaborato, un veloce Google otterrà anche questo).

  var canvasOffset=$("#canvas").offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top; 

Quindi, nel tuo gestore del mouse, puoi ottenere il mouse X / Y in questo modo:

  function handleMouseDown(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); } 

Ecco un codice illustrativo e un violino che mostra come tracciare con successo gli eventi del mouse sulla canvas:

http://jsfiddle.net/m1erickson/WB7Zu/

           

Move, press and release the mouse

Down

Move

Up

Out

Fai riferimento a questa domanda: Il mouseEvent.offsetX che ottengo è molto più grande delle dimensioni effettive del canvas . Ho dato una funzione che si adatta perfettamente alla tua situazione

Il modo più semplice per calcolare la posizione di spostamento del mouse o del mouse corretta su un evento canvas è utilizzare questa piccola equazione:

 canvas.addEventListener('click', event => { let bound = canvas.getBoundingClientRect(); let x = event.clientX - bound.left - canvas.clientLeft; let y = event.clientY - bound.top - canvas.clientTop; context.fillRect(x, y, 16, 16); }); 

Se la canvas ha spaziatura-sinistra o padding-top , sottrai x e y tramite:

x -= parseFloat(style['padding-left'].replace('px'));
y -= parseFloat(style['padding-top'].replace('px'));