HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Detecting collision of two divs

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
twodetectingcollisiondivs

Problem

I have two divs as seen in this JSFiddle. To recreate the problem, keep clicking on the Gray container till both divisions touch each other.

The purpose is to execute a certain function once the green div touches the red one. The problem is that, this step callback as seen from the following code and demo, gets called multiple times. It is not something that I want to happen.

One method that would fix the problem is to keep a certain flag variable which turns True once step is executed. But I'm not sure that's enough as there needs to be a way to break out of the step callback.

I want to know:

-
If there is a better/efficient way to detect collision of two divs than using jQuery Collision.

-
How to stop the step callback after its executed once.

HTML:


    
    


JavaScript:

$(document).ready(function () {
    var hit_list;
    $(".container").click(function () {

        $(".menu").stop().animate({
            left: "+=100px"
        }, {
           duration: 300,
           complete: function () {
               $(".menu").animate({
                   left: "0"
               }, 800);
           },
           step: function(){
               //Test for collision
               hit_list = $(".menu").collision(".test");
               if (hit_list.length != 0) {
                   $(".container").append("Welcome Earthling");
               }
           }
         });
     });
 });

Solution

In response to not triggering the message repeatedly, I would store the previous check for a collision so you know if a collision has started or ended.

If there is a collision but your previous check didn't show a collision, then you have a new collision and you can trigger the event. However, if the previous check did show a collision, don't fire the callback since it has already been fired.

I would also recommend using custom jQuery events. This allows you to separate out the callback from the animation code.

Below I've adapted your code to trigger a custom event when you detect a collision has started or ended. Here's the updated javascript (also available as a modification of your fiddle):

$(document).ready(function () {

    $(".menu").data("collision", false);
    $(".menu").on("collision_start", function () {
        $(".container").append("Welcome Earthling");
    });

    $(".container").click(function () {

        $(".menu").stop().animate({
            left: "+=100px"
        }, {
            duration: 300,
            complete: function () {
                $(".menu").animate({
                    left: "0"
                }, 800);
            },
            step: function () {
                //Test for collision
                var hit_list = $(this).collision(".test");
                var current_collision = hit_list.length != 0;

                // compare this to what we last observed
                var changed_collision = current_collision != $(this).data("collision");

                if (changed_collision) {
                    // save this new observation for future comparisons
                    $(this).data("collision", current_collision);

                    // trigger an event
                    $(this).trigger("collision_" + (current_collision ? "start" : "stop"));
                }
            }
        });
    });
});

Code Snippets

$(document).ready(function () {

    $(".menu").data("collision", false);
    $(".menu").on("collision_start", function () {
        $(".container").append("Welcome Earthling");
    });

    $(".container").click(function () {

        $(".menu").stop().animate({
            left: "+=100px"
        }, {
            duration: 300,
            complete: function () {
                $(".menu").animate({
                    left: "0"
                }, 800);
            },
            step: function () {
                //Test for collision
                var hit_list = $(this).collision(".test");
                var current_collision = hit_list.length != 0;

                // compare this to what we last observed
                var changed_collision = current_collision != $(this).data("collision");

                if (changed_collision) {
                    // save this new observation for future comparisons
                    $(this).data("collision", current_collision);

                    // trigger an event
                    $(this).trigger("collision_" + (current_collision ? "start" : "stop"));
                }
            }
        });
    });
});

Context

StackExchange Code Review Q#42735, answer score: 6

Revisions (0)

No revisions yet.