Wie erkennt man, ob zwei <div>
Elemente kollidiert sind?
Die beiden Divs sind einfache farbige Kästchen, die senkrecht zueinander verlaufen, also keine komplizierten Formen oder Winkel.
javascript
jquery
html
collision-detection
Chris Armstrong
quelle
quelle
Antworten:
var overlaps = (function () { function getPositions( elem ) { var pos, width, height; pos = $( elem ).position(); width = $( elem ).width(); height = $( elem ).height(); return [ [ pos.left, pos.left + width ], [ pos.top, pos.top + height ] ]; } function comparePositions( p1, p2 ) { var r1, r2; r1 = p1[0] < p2[0] ? p1 : p2; r2 = p1[0] < p2[0] ? p2 : p1; return r1[1] > r2[0] || r1[0] === r2[0]; } return function ( a, b ) { var pos1 = getPositions( a ), pos2 = getPositions( b ); return comparePositions( pos1[0], pos2[0] ) && comparePositions( pos1[1], pos2[1] ); }; })(); $(function () { var area = $( '#area' )[0], box = $( '#box0' )[0], html; html = $( area ).children().not( box ).map( function ( i ) { return '<p>Red box + Box ' + ( i + 1 ) + ' = ' + overlaps( box, this ) + '</p>'; }).get().join( '' ); $( 'body' ).append( html ); });
body { padding: 30px; color: #444; font-family: Arial, sans-serif; } h1 { font-size: 24px; margin-bottom: 20px; } #area { border: 2px solid gray; width: 500px; height: 400px; position: relative; } #area > div { background-color: rgba(122, 122, 122, 0.3); position: absolute; text-align: center; font-size: 50px; width: 60px; height: 60px; } #box0 { background-color: rgba(255, 0, 0, 0.5) !important; top: 150px; left: 150px; } #box1 { top: 260px; left: 50px; } #box2 { top: 110px; left: 160px; } #box3 { top: 200px; left: 200px; } #box4 { top: 50px; left: 400px; } p { margin: 5px 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <h1>Detect overlapping with JavaScript</h1> <div id="area"> <div id="box0"></div> <div id="box1">1</div> <div id="box2">2</div> <div id="box3">3</div> <div id="box4">4</div> </div>
Allgemeine Idee - Sie erhalten den Versatz und die Abmessung der Felder und prüfen, ob sie sich überlappen.
Wenn Sie möchten, dass es aktualisiert wird, können Sie Folgendes verwenden
setInterval
:function detectOverlapping() { // code that detects if the box overlaps with a moving box setInterval(detectOverlapping, 25); } detectOverlapping();
Beachten Sie außerdem, dass Sie die Funktion für Ihr spezielles Beispiel optimieren können.
Sie müssen die Abmessungen der Box nicht wiederholt lesen (wie ich es in meinem Code tue), da sie fest sind. Sie können sie beim Laden der Seite (in eine Variable) lesen und dann einfach die Variable lesen
Die horizontale Position des Kästchens ändert sich nicht (es sei denn, der Benutzer ändert die Größe des Fensters). Die vertikalen Positionen der Fahrzeugboxen ändern sich nicht. Daher müssen diese Werte auch nicht wiederholt gelesen werden, sondern können auch in Variablen gespeichert werden.
Sie müssen nicht immer testen, ob sich die kleine Box mit allen Auto-Boxen überschneidet. Sie können anhand der vertikalen Position herausfinden, auf welcher Fahrspur sich die Box gerade befindet, und nur die spezifische Fahrzeugbox dieser Fahrspur testen.
quelle
$.offset()
als$.position()
in Zeile 4? Auf diese Weise sollte es funktionieren, um die Kollision aller Elemente im DOM zu überprüfen, anstatt nur an Geschwisterelementen zu arbeiten.Ich glaube, das ist der einfachste Weg: http://plugins.jquery.com/project/collidable
Hier ist noch eine auf Deutsch: http://www.48design.de/news/2009/11/20/kollisionsabfrage-per-jquery-plugin-update-v11-8/
Ich würde es versuchen.
--AKTUALISIEREN--
Ich kann momentan nicht wirklich viel Zeit damit verbringen, aber ich kann es, wenn ich nach Hause komme, wenn niemand außer dir antwortet; ich würde etwas tun wie:
setInterval(function(){ //First step would be to get the offset of item 1 and item 2 //Second would be to get the width of each //Third would be to check if the offset+width ever overlaps //the offset+width of the 2nd //Fourth would be, if so, do X or set a class... },10);
quelle
Es ist etwas spät, aber ich denke, Sie könnten diesen Ansatz verwenden, den ich versucht habe, als ich mit einer ähnlichen Situation konfrontiert war. Der Vorteil hierbei ist, dass kein zusätzliches Plugin oder Skripte beteiligt sind und Sie auch keine leistungshungrigen Abfragen einführen müssen. Diese Technik verwendet die integrierten Methoden und Ereignisse, die Jquery's Droppable zu bieten hat.
Ok, genug gesagt, hier ist die Lösungstechnik: Sagen Sie, wenn Sie zwei Elemente haben (Bilder in meinem Fall) und Sie nicht möchten, dass sie sich überlappen oder erkennen, wenn sie dies tun, machen Sie die beiden Elemente zu einem Droppable und lassen Sie sie "akzeptieren". gegenseitig:
Die 'CONFIG_COLLISSION_PREVENTION_DROPPABLE' sieht folgendermaßen aus:
var originatingOffset = null; CONFIG_COLLISSION_PREVENTION_DROPPABLE = { tolerance: "touch", activate : function (event, ui) { // note the initial position/offset when drag starts // will be usedful in drop handler to check if the move // occurred and in cae overlap occurred, restore the original positions. originatingOffset = ui.offset; }, drop : function (event, ui) { // If this callback gets invoked, the overlap has occurred. // Use this method to either generate a custom event etc. // Here, i used it to nullify the move and resetting the dragged element's // position back to it's original position/offset // (which was captured in the 'activate' handler) $(ui.draggable).animate({ top: originatingOffset.top + "px", left: originatingOffset.left + "px" }, 300); } }
Die Handler "Aktivieren" und "Löschen" beziehen sich auf die Ereignisse "Dropaktivieren" und "Löschen" des Plugins "Droppable"
Hier ist der Schlüssel der Drop-Callback. Immer wenn sich eines der beiden Elemente überlappt und sie übereinander fallen, wird der "Tropfen" aufgerufen. Dies ist der Ort, an dem Aktionen erkannt und ausgeführt werden können, benutzerdefinierte Ereignisse gesendet oder andere Aktionen aufgerufen werden können (ich habe mich hier dafür entschieden, die Positionen des überlappenden Elements auf die ursprüngliche Position zurückzusetzen, als das Ziehen gestartet wurde, die im Rückruf "Aktivieren" erfasst wurde).
Das ist es. Keine Abfrage, keine Plugins, nur die eingebauten Ereignisse.
Nun, es können andere Optimierungen / Erweiterungen vorgenommen werden, dies war einfach der erste Schuss aus meinem Kopf, der funktioniert hat :)
Sie können auch die Ereignisse "Dropover" und "Dropout" verwenden, um dem Benutzer zu signalisieren und ein visuelles Feedback zu erstellen, dass sich zwei Elemente überlappen, während sie sich möglicherweise noch in Bewegung befinden.
var CLASS_INVALID = "invalid"; // .invalid { border: 1px solid red; } ... $.extend(CONFIG_COLLISSION_PREVENTION_DROPPABLE, { over : function (event, ui) { // When an element is over another, it gets detected here; // while it may still be moved. // the draggable element becomes 'invalid' and so apply the class here $(ui.draggable).addClass(CLASS_INVALID); }, out : function(event, ui) { // the element has exited the overlapped droppable now // So element is valid now and so remove the invalid class from it $(ui.draggable).removeClass(CLASS_INVALID); } });
Hoffe das hilft!
quelle
EDIT: Ich habe einen Blog-Beitrag auf meiner Website geschrieben. Hier ein Link dazu. http://area36.nl/2014/12/creating-your-own-collision-detection-function-in-javascript/
Nun, ich hatte das gleiche Problem, aber dank der Antwort von Oscar Godson bekam ich eine Funktion, die funktioniert. Ich habe Jquery für einfaches Codieren verwendet und weil ich faul bin; p. Ich habe die Funktion in eine andere Funktion eingefügt, die jede Sekunde ausgelöst wird. Denken Sie also daran.
function collidesWith (element1, element2) { var Element1 = {}; var Element2 = {}; Element1.top = $(element1).offset().top; Element1.left = $(element1).offset().left; Element1.right = Number($(element1).offset().left) + Number($(element1).width()); Element1.bottom = Number($(element1).offset().top) + Number($(element1).height()); Element2.top = $(element2).offset().top; Element2.left = $(element2).offset().left; Element2.right = Number($(element2).offset().left) + Number($(element2).width()); Element2.bottom = Number($(element2).offset().top) + Number($(element2).height()); if (Element1.right > Element2.left && Element1.left < Element2.right && Element1.top < Element2.bottom && Element1.bottom > Element2.top) { // Do your stuff here } }
Was es tut, ist im Grunde, dass es alle Werte von
element1
und dann alle Werte von erhältelement2
. Dann werden mit Hilfe einiger Berechnungen alle Werte ermittelt. Dannif
vergleicht es in der Aussage das Quadrat vonelement1
mit dem Quadrat vonelement2
. Wenn die Werte vonelement1
zwischen den linken, rechten, oberen und unteren Werten von liegenelement2
. Wenn dies zutrifft, wird der Code unten ausgeführt.quelle
Ich bin selbst auf dieses allgemeine Problem gestoßen, also habe ich (vollständige Offenlegung) ein Plugin dafür erstellt. Versuchen Sie Folgendes für einfache Kollisionsabfragen zu statischen Objekten:
http://sourceforge.net/projects/jquerycollision/
So können Sie eine Liste überlappender Kollisionsfelder abrufen (oder keine, wenn keine Kollision vorliegt):
hits = $("#collider").collision(".obstacles");
Oder verwenden Sie Folgendes, um beim "Ziehen" ein Kollisionsereignis zu erhalten:
http://sourceforge.net/apps/mediawiki/jquidragcollide/?source=navbar#collision
Dadurch erhalten Sie ein "Kollisions" -Ereignis, mit dem Sie eine Verbindung herstellen können. (Oder ein "Protrusions" -Ereignis, um zu sehen, ob ein Div einem anderen Div entgeht, das es derzeit enthält.)
$(draggable).bind( "collision", function(event,ui) { ... } );
Wenn Sie Kollisionen während einer anderen Bewegung als dem Ziehen überprüfen, rufen Sie einfach das Original wiederholt auf, es ist ziemlich schnell. Hinweis: Das Ziehen spielt beim Ändern der Größe nicht gut.
quelle
Post ist alt, kann es jemandem helfen ...
function CheckDiv() { var ediv1 = document.getElementById('DIV1'); var ediv2 = document.getElementById('DIV2'); ediv1.top = $(ediv1).offset().top; ediv1.left = $(ediv1).offset().left; ediv1.right = Number($(ediv1).offset().left) + Number($(ediv1).width()); ediv1.bottom = Number($(ediv1).offset().top) + Number($(ediv1).height()); ediv2.top = $(ediv2).offset().top; ediv2.left = $(ediv2).offset().left; ediv2.right = Number($(ediv2).offset().left) + Number($(ediv2).width()); ediv2.bottom = Number($(ediv2).offset().top) + Number($(ediv2).height()); if (ediv1.right > ediv2.left && ediv1.left < ediv2.right && ediv1.top < ediv2.bottom && ediv1.bottom > ediv2.top) { alert("hi"); } if (ediv1.left > ediv2.left && ediv1.top > ediv2.top && ediv1.right < ediv2.right && ediv1.bottom < ediv2.bottom) { alert("hello"); } }
quelle
Sie können dies mit getBoundingClientRect () tun
function isOverlapping(div1, div2){ const div1 = div1.getBoundingClientRect(); const div2 = div2.getBoundingClientRect(); return (div1.right > div2.left && div1.left < div2.right && div1.bottom > div2.top && div1.top < div2.bottom) }
quelle