Ich möchte eine kleine Mal-App mit Canvas erstellen. Ich muss also die Position der Maus auf der Leinwand finden.
Antworten
Zu viele Anzeigen?Ein guter Bericht über die Schwierigkeit dieses Problems findet sich hier: http://www.quirksmode.org/js/events_properties.html#position
Mit der dort beschriebenen Technik können Sie die Position der Maus im Dokument ermitteln. Dann müssen Sie nur noch prüfen, ob sie sich innerhalb des Begrenzungsrahmens Ihres Elements befindet, was Sie durch den Aufruf von element.getBoundingClientRect()
die ein Objekt mit den folgenden Eigenschaften zurückgibt: { bottom, height, left, right, top, width }
. Von dort aus ist es trivial, herauszufinden, ob das Ereignis innerhalb Ihres Elements stattgefunden hat oder nicht.
Die Antwort von Mark van Wyk hat mich zwar in die richtige Richtung geführt, aber das Problem nicht ganz gelöst. Ich hatte immer noch einen Versatz beim Malen von Elementen, die in einem anderen Element enthalten waren.
Folgendes hat das Problem für mich gelöst:
x = e.pageX - this.offsetLeft - $(elem).offset().left;
y = e.pageY - this.offsetTop - $(elem).offset().top;
Mit anderen Worten - ich habe einfach alle Offsets von allen verschachtelten Elementen gestapelt
Diejenigen unter Ihnen, die normale Websites oder PWAs (Progressive Web Apps) für mobile Geräte und/oder Laptops/Monitore mit Touchscreens entwickeln, sind hier gelandet, weil sie vielleicht an Mausereignisse gewöhnt sind und die manchmal schmerzhafte Erfahrung von Touch-Ereignissen neu ist... juhu!
Es gibt nur 3 Regeln:
- Tun Sie so wenig wie möglich während
mousemove
otouchmove
Veranstaltungen. - Tun Sie so viel wie möglich während
mousedown
otouchstart
Veranstaltungen. - Abbrechen der Weitergabe und Verhindern von Standardwerten für Berührungsereignisse, um zu verhindern, dass Mausereignisse auch auf Hybridgeräten ausgelöst werden.
Unnötig zu erwähnen, dass die Dinge komplizierter sind mit touch
Ereignisse, weil es mehr als eines geben kann und sie flexibler (komplizierter) sind als Mausereignisse. Ich werde hier nur eine einzige Berührung behandeln. Ja, ich bin faul, aber es ist die häufigste Art der Berührung, so dort.
var posTop;
var posLeft;
function handleMouseDown(evt) {
var e = evt || window.event; // Because Firefox, etc.
posTop = e.target.offsetTop;
posLeft = e.target.offsetLeft;
e.target.style.background = "red";
// The statement above would be better handled by CSS
// but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
var e = evt || window.event;
var x = e.offsetX; // Wonderfully
var y = e.offsetY; // Simple!
e.target.innerHTML = "Mouse: " + x + ", " + y;
if (posTop)
e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
var e = evt || window.event;
e.target.innerHTML = "";
}
function handleMouseUp(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
var e = evt || window.event;
var rect = e.target.getBoundingClientRect();
posTop = rect.top;
posLeft = rect.left;
e.target.style.background = "green";
e.preventDefault(); // Unnecessary if using Vue.js
e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
var e = evt || window.event;
var pageX = e.touches[0].clientX; // Touches are page-relative
var pageY = e.touches[0].clientY; // not target-relative
var x = pageX - posLeft;
var y = pageY - posTop;
e.target.innerHTML = "Touch: " + x + ", " + y;
e.target.innerHTML += "<br>" + pageX + ", " + pageY;
e.preventDefault();
e.stopPropagation();
}
function handleTouchEnd(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
// Yes, I'm being lazy and doing the same as mouseout here
// but obviously you could do something different if needed.
e.preventDefault();
e.stopPropagation();
}
div {
background: yellow;
height: 100px;
left: 50px;
position: absolute;
top: 80px;
user-select: none; /* Disable text selection */
-ms-user-select: none;
width: 100px;
}
<div
onmousedown="handleMouseDown()"
onmousemove="handleMouseMove()"
onmouseout="handleMouseOut()"
onmouseup="handleMouseUp()"
ontouchstart="handleTouchStart()"
ontouchmove="handleTouchMove()"
ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.
Bevorzugt verwenden Vue.js ? Ich schon! Dann würde Ihr HTML folgendermaßen aussehen:
<div @mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@touchstart.stop.prevent="handleTouchStart"
@touchmove.stop.prevent="handleTouchMove"
@touchend.stop.prevent="handleTouchEnd">