Détecter l'emplacement du clic de souris dans le canevas

J'ai vraiment un problème qui tente de définir une fonction pour laquelle je clique sur l'espace vide. Jusqu'à présent, j'ai réussi à définir où je clique sur un objet – dont il y a 10 – mais maintenant, j'ai besoin d'une fonction distincte lorsque je ne clique sur aucun des objets. L'idée générale se trouve à http://deciballs.co.uk/experience.html . Les objets sont les anneaux. Mon code est ci-dessous … Des idées?

var shapeObj = function (context, canvas, settingsBox, radius) { this.ctx = context; this.canvas = canvas; this.sBox = settingsBox; this.frequencies = new Array(220, 440, 1024, 2048); this.cols = new Array(255, 225, 200, 175, 150); this.strokes = new Array(1, 1.5, 2); this.waves = new Array('sine', 'sawtooth', 'triangle', 'square'); this.properties = { dur: Math.random()*0.5, freq: this.frequencies[Math.floor(Math.random() * this.frequencies.length)], radius: radius, stroke: this.strokes[Math.floor(Math.random() * this.strokes.length)], speed: Math.random()*6-3, vol: Math.random()*10, col1: this.cols[Math.floor(Math.random() * this.cols.length)], col2: this.cols[Math.floor(Math.random() * this.cols.length)], col3: this.cols[Math.floor(Math.random() * this.cols.length)], alpha: 0, wave: this.waves[Math.floor(Math.random() * this.waves.length)], delay: 0 } this.x = Math.random()*this.ctx.canvas.width; this.y = Math.random()*this.ctx.canvas.height; this.vx = 0.5; this.vy = 1; this.draw = function () { this.ctx.beginPath(); this.ctx.arc(this.x, this.y, this.properties.radius, 0, Math.PI*2, false); this.ctx.closePath(); this.ctx.stroke(); this.ctx.fill(); } this.clickTest = function (e) { var canvasOffset = this.canvas.offset(); var canvasX = Math.floor(e.pageX-canvasOffset.left); var canvasY = Math.floor(e.pageY-canvasOffset.top); var dX = this.x-canvasX; var dY = this.y-canvasY; var distance = Math.sqrt((dX*dX)+(dY*dY)); if (distance < this.properties.radius) { this.manageClick(); } else { this.properties.alpha = 0; } }; this.manageClick = function () { this.sBox.populate(this.properties, this); var divs = document.getElementsByTagName('section'); for(var i = 0, e = divs[0], n = divs.length; i < n; e = divs[++i]){ e.className='class2'; } this.properties.alpha = 0.5; } } 

Obtenir des clics de souris parfaits est légèrement délicat, je partagerai le code de souris le plus pare-balles que j'ai créé jusqu'à présent. Il fonctionne sur tous les navigateurs avec toutes sortes de rembourrage, de marge, de bordure et d'add-ons (comme la barre supérieure Stumbleupon).

 // Creates an object with x and y defined, // set to the mouse position relative to the state's canvas // If you wanna be super-correct this can be tricky, // we have to worry about padding and borders // takes an event and a reference to the canvas function getMouse(e, canvas) { var element = canvas, offsetX = 0, offsetY = 0, mx, my; // Compute the total offset. It's possible to cache this if you want if (element.offsetParent !== undefined) { do { offsetX += element.offsetLeft; offsetY += element.offsetTop; } while ((element = element.offsetParent)); } // Add padding and border style widths to offset // Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar) // This part is not strictly necessary, it depends on your styling offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft; offsetY += stylePaddingTop + styleBorderTop + htmlTop; mx = e.pageX - offsetX; my = e.pageY - offsetY; // We return a simple javascript object with x and y defined return {x: mx, y: my}; } 

Vous remarquerez que j'utilise certaines variables (facultatives) qui ne sont pas définies dans la fonction. Elles sont:

  stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0; stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0; styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0; styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0; // Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page // They will mess up mouse coordinates and this fixes that var html = document.body.parentNode; htmlTop = html.offsetTop; htmlLeft = html.offsetLeft; 

Je recommande seulement de les calculer une fois, c'est pourquoi ils ne sont pas dans la fonction getMouse .


Vous devriez vraiment avoir un seul chapeau de fonction qui gère les clics de la souris, appelle getMouse une fois, puis passe une liste d'objets en vérifiant chacun avec x et y. Pseudocode:

 function onMouseDown(e) { var mouse = getMouse(e, canvas) var l = myObjects.length; var found = false; // Maybe "deselect" them all right here for (var i = 0; i < l; i++) { if (distance sqrt to myObjects[i]) { found = true; myObjects[i].ManageClickOrWhateverYouWantHere() } break; } // And now we can know if we clicked on empty space or not! if (!found) { // No objects found at the click, so nothing has been clicked on // do some relevant things here because of that // I presume from your question this may be part of what you want } }