Asked  6 Months ago    Answers:  5   Viewed   45 times

How to detect if two <div> elements have collided?

The two divs are simple coloured boxes travelling perpendicular to each other, so no complicated shapes or angles.

 Answers

46

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>

General idea - you get the offset and dimension of the boxes and check whether they overlap.

If you want it to update, you can use setInterval:

function detectOverlapping() {
    // code that detects if the box overlaps with a moving box
    setInterval(detectOverlapping, 25);
}

detectOverlapping();  

Also, note that you can optimize the function for your specific example.

  • you don't have to read the box dimensions repeatedly (like I do in my code) since they are fixed. You can read them on page load (into a variable) and then just read the variable

  • the horizontal position of the little box does not change (unless the user resizes the window). The vertical positions of the car boxes does not change. Therefore, those values also do not have to be read repeatedly, but can also be stored into variables.

  • you don't have to test whether the little box overlaps with all car boxes at all times. You can - based on its vertical position - figure out in which lane the box is currently, and test only the specific car box from that lane.

Tuesday, June 1, 2021
 
Dunc
answered 6 Months ago
23

canplaythrough is the event that should fire when enough data has downloaded to play without buffering.

From the Opera teams excellent (although maybe very slightly dated now) resource Everything you need to know about HTML5 video and audio

If the load is successful, whether using the src attribute or using source elements, then as data is being downloaded, progress events are fired. When enough data has been loaded to determine the video's dimensions and duration, a loadedmetadata event is fired. When enough data has been loaded to render a frame, the loadeddata event is fired. When enugh data has been loaded to be able to play a little bit of the video, a canplay event is fired. When the browser determines that it can play through the whole video without stopping for downloading more data, a canplaythrough event is fired; this is also when the video starts playing if it has a autoplay attribute.

'canplaythrough' support matrix available here: https://caniuse.com/mdn-api_htmlmediaelement_canplaythrough_event

You can get around the support limitations by binding the load element to the same function, as it will trigger on those.

Wednesday, July 28, 2021
 
Easen
answered 4 Months ago
23

Use Line Line intersection

https://www.topcoder.com/community/data-science/data-science-tutorials/geometry-concepts-line-intersection-and-its-applications/#line_line_intersection

Also consider the possibility that some vertex might be touching one of the sides of the other triangle.

http://www.blackpawn.com/texts/pointinpoly/default.html

function SameSide(p1,p2, a,b)
    cp1 = CrossProduct(b-a, p1-a)
    cp2 = CrossProduct(b-a, p2-a)
    if DotProduct(cp1, cp2) >= 0 then return true
    else return false

function PointInTriangle(p, a,b,c)
    if SameSide(p,a, b,c) and SameSide(p,b, a,c)
        and SameSide(p,c, a,b) then return true
    else return false

Or look at this link and scroll down

http://compsci.ca/v3/viewtopic.php?t=6034

Tuesday, August 10, 2021
 
laukok
answered 4 Months ago
91

As you mentioned that the implementation language does not matter, I will give you a generic solution for detecting collision of round objects.

Also, from what I gather, all the objects in the scene are circles. The solution below does not apply for detecting collision between a circle and some other shape.

Suppose you have two circles c1 and c2. Suppose the corresponding radii are c1.r and c2.r, and the centers are (c1.x,c1.y) and (c2.x, c2.y), then the following function will tell whether c1 and c2 are in collision

boolean areColliding(Circle c1, Circle c2){

   center_distance = sqrt((x1-x2)^2 +(y1-y2)^2);  //this is the distance between the centers of the two circles.

  if((c1.r+c2.r) < center_distance)
           return false;
  else
          return true;

}

This pseudo-code function will return true if the circles are colliding, false otherwise.

Basically, what the function does is check whether the distance between the centers of the circles is greater than the sum of their respective radius.

Friday, August 20, 2021
 
erotsppa
answered 4 Months ago
46

Here's one way using getImageData to manipulate the hue of each image pixel:

  • Use getImageData to fetch the RGBA color data of each pixel

  • Convert the RGBA color to HSL color. The H in HSL means Hue which is what we normally think of as "color".

  • If the Hue of an original pixel is red-ish (Hue<30 or Hue>300) then shift the hue by the amount specified in your range control. If you want to shift from red to blue, then your slider should shift the color (Hue) from 0 to -.33.

Note: getImageData requires that the image originate on the same domain as the webpage or else you will get a cross-domain security error.

Here's example code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var imgData,data,originalData;

$myslider=$('#myslider');
$myslider.attr({min:0,max:33}).val(0);
$myslider.on('input change',function(){
  var value=parseInt($(this).val());
  HueShift(30,300,-value/100);
});

var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="http://icons.iconarchive.com/icons/iconshow/transport/256/Sportscar-car-icon.png";
function start(){
  cw=canvas.width=img.width;
  ch=canvas.height=img.height;
  ctx.drawImage(img,0,0);

  imgData=ctx.getImageData(0,0,cw,ch);
  data=imgData.data;
  imgData1=ctx.getImageData(0,0,cw,ch);
  originalData=imgData1.data;

}



function HueShift(hue1,hue2,shift){

  for(var i=0;i<data.length;i+=4){
    red=originalData[i+0];
    green=originalData[i+1];
    blue=originalData[i+2];
    alpha=originalData[i+3];

    // skip transparent/semiTransparent pixels
    if(alpha<230){continue;}

    var hsl=rgbToHsl(red,green,blue);
    var hue=hsl.h*360;

    // change redish pixels to the new color
    if(hue<30 || hue>300){


      var newRgb=hslToRgb(hsl.h+shift,hsl.s,hsl.l);
      data[i+0]=newRgb.r;
      data[i+1]=newRgb.g;
      data[i+2]=newRgb.b;
      data[i+3]=255;
    }
  }    
  ctx.putImageData(imgData,0,0);
}






////////////////////////
// Helper functions
//

function rgbToHsl(r, g, b){
  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;
  if(max == min){
    h = s = 0; // achromatic
  }else{
    var d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch(max){
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h /= 6;
  }
  return({ h:h, s:s, l:l });
}

function hslToRgb(h, s, l){
  var r, g, b;
  if(s == 0){
    r = g = b = l; // achromatic
  }else{
    function hue2rgb(p, q, t){
      if(t < 0) t += 1;
      if(t > 1) t -= 1;
      if(t < 1/6) return p + (q - p) * 6 * t;
      if(t < 1/2) return q;
      if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
      return p;
    }
    var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    var p = 2 * l - q;
    r = hue2rgb(p, q, h + 1/3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1/3);
  }
  return({
    r:Math.round(r * 255),
    g:Math.round(g * 255),
    b:Math.round(b * 255),
  });
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Change the slider to change the car color</h4>
<input id=myslider type=range min=0 max=100 value=0><br>
<canvas id="canvas" width=300 height=300></canvas>
Tuesday, October 5, 2021
 
LDropl
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share