Detecting if two rotating divs collide using jQuery

I would like to determine if two rotating divs collide. I know how to do it if they don’t rotate, but I don’t know how to do it when they really are.

I tried some conflict plugins such as jQuery Collision ( http://sourceforge.net/projects/jquerycollision/ ), but they did not work when the div was rotated.

I rotated the divs using the CSS transform property.

+6
source share
3 answers

This is not 100% accurate, but it works in most cases, I used the algorithm from here :

function isUndefined(a) { return a === undefined; } /** * Helper function to determine whether there is an intersection between the two polygons described * by the lists of vertices. Uses the Separating Axis Theorem * * @param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon * @param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon * @return true if there is any intersection between the 2 polygons, false otherwise */ function doPolygonsIntersect (a, b) { var polygons = [a, b]; var minA, maxA, projected, i, i1, j, minB, maxB; for (i = 0; i < polygons.length; i++) { // for each polygon, look at each edge of the polygon, and determine if it separates // the two shapes var polygon = polygons[i]; for (i1 = 0; i1 < polygon.length; i1++) { // grab 2 vertices to create an edge var i2 = (i1 + 1) % polygon.length; var p1 = polygon[i1]; var p2 = polygon[i2]; // find the line perpendicular to this edge var normal = { x: p2.y - p1.y, y: p1.x - p2.x }; minA = maxA = undefined; // for each vertex in the first shape, project it onto the line perpendicular to the edge // and keep track of the min and max of these values for (j = 0; j < a.length; j++) { projected = normal.x * a[j].x + normal.y * a[j].y; if (isUndefined(minA) || projected < minA) { minA = projected; } if (isUndefined(maxA) || projected > maxA) { maxA = projected; } } // for each vertex in the second shape, project it onto the line perpendicular to the edge // and keep track of the min and max of these values minB = maxB = undefined; for (j = 0; j < b.length; j++) { projected = normal.x * b[j].x + normal.y * b[j].y; if (isUndefined(minB) || projected < minB) { minB = projected; } if (isUndefined(maxB) || projected > maxB) { maxB = projected; } } // if there is no overlap between the projects, the edge we are looking at separates the two // polygons, and we know there is no overlap if (maxA < minB || maxB < minA) { console.log("polygons don't intersect!"); return false; } } } return true; }; $('#r').click(function() { var rota = Math.floor( Math.random() * 100 ), rotb = Math.floor( Math.random() * 100 ), pointsa = new Array(4), pointsb = new Array(4); $('#a').css('transform', 'rotateZ(' + rota + 'deg)'); $('#b').css('transform', 'rotateZ(' + rotb + 'deg)'); $('#a div').each(function(i) { pointsa[i] = {x: parseInt($(this).offset().left), y: parseInt($(this).offset().top)}; }); $('#b div').each(function(i) { pointsb[i] = {x: parseInt($(this).offset().left), y: parseInt($(this).offset().top)}; }); $('#s').val("intersection: " + doPolygonsIntersect(pointsb, pointsa).toString()); }); 

working violin

This is not the best way to do this. I suppose my script does basically random rotation between 0 and 100 degrees, gets the x and y positions of each angle (using divs, you can do it with math, also (i can not: D)) and run the algorithm using these coordinates.

+4
source

I found overlaps.js yckart.

I made a fiddle with rotating divs here: http://jsfiddle.net/n3M5e/

You can change the rotation of divs in CSS yourself, and detection still works well.

overlaps.js

 (function ($) { $.fn.overlaps = function (obj) { var elems = { targets: [], hits: [] }; this.each(function () { var bounds = $(this).offset(); bounds.right = bounds.left + $(this).outerWidth(); bounds.bottom = bounds.top + $(this).outerHeight(); var compare = $(obj).offset(); compare.right = compare.left + $(obj).outerWidth(); compare.bottom = compare.top + $(obj).outerHeight(); if (!(compare.right < bounds.left || compare.left > bounds.right || compare.bottom < bounds.top || compare.top > bounds.bottom)) { elems.targets.push(this); elems.hits.push(obj); } }); return elems; }; }(jQuery)); 

Hope I helped.

EDIT:

Thanks to @jbrosi, overlaps.js doesn't really work very well with rotated divs.

-1
source

You are looking for collision detection div.

If you want to raise an event, you need to test many times, but it would be better to just run a function on all your divs.

A demo version of the sample is located at http://jsfiddle.net/nGRwt/7/

Here is the function you need to use

 function collision($div1, $div2) { var x1 = $div1.offset().left; var y1 = $div1.offset().top; var h1 = $div1.outerHeight(true); var w1 = $div1.outerWidth(true); var b1 = y1 + h1; var r1 = x1 + w1; var x2 = $div2.offset().left; var y2 = $div2.offset().top; var h2 = $div2.outerHeight(true); var w2 = $div2.outerWidth(true); var b2 = y2 + h2; var r2 = x2 + w2; if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false; return true; } 

Other demo

You can also refer to http://jsfiddle.net/98sAG/ for conflict detection.

To do this, use the code below:

 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] ); }; })(); 

Hope this helps you :)

-1
source

Source: https://habr.com/ru/post/972880/


All Articles