Search code examples
javascriptjqueryhtmlkineticjs

Detect drop event on individual objects in kineticJS


Main idea

Creating a match the following exercise with the right side dots being draggle and left side dots are the targets.

enter image description here

Red dots are draggable and are to be dropped on the blue dots.

Target

Each dot has an associated value with them, furthermore, once a red dot is dropped on a blue dot no other red dot can be placed on the same blue dot.

Approach

Storing coordinates of each blue dot in an array, and once a red dot is placed closeby a blue dot, the information related to that dot is removed from the array (hence making it invisible).

Problem

How can I detect a drop event for each red dot, most solutions available online suggest having a .on even on the shape. However, how should I uniquely identify which one?

Resource

JSFiddle: http://jsfiddle.net/wLcxchfv/1/


Solution

  • Here's one way to detect red circle drop events and test if they intersect a blue circle.

    • Assign name:'blue' when defining every blue circle (kinetic 'name' is like a CSS 'class'):

      name:'blue'

    • Listen for drag-drops on all red circles:

      anyRedCircle.on('dragend',function(){});

    • Fetch all the blue circles:

      stage.find(".blue")

    • Test if this red circle was dropped on one of those blue circles:

      // fetch all circles with name=='blue' and feed them into a function 
      stage.find(".blue").each(function(b){
          // b is a blue circle
          var dx=this.x()-b.x();
          var dy=this.y()-b.y();
          if(dx*dx+dy*dy<radius*radius){
              // this red circle was dropped on this blue circle
          }
      });
      

      });

    Example code and a demo: http://jsfiddle.net/m1erickson/apdohmcm/

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Prototype</title>
        <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
        <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
    <style>
    body{padding:20px;}
    #container{
      border:solid 1px #ccc;
      margin-top: 10px;
      width:350px;
      height:350px;
    }
    </style>        
    <script>
    $(function(){
    
        var stage = new Kinetic.Stage({
            container: 'container',
            width: 350,
            height: 350
        });
        var layer = new Kinetic.Layer();
        stage.add(layer);
    
        var radius=10;
        var $last=$("#lastHit");
    
        for(var i=0;i<5;i++){
            makeCirclePair(30,i*30+40,150,i*30+40,(i+1)*10);
        }
    
    
        function makeCirclePair(redX,redY,blueX,blueY,value){
            var blue=makeCircle(blueX,blueY,'blue',false,value);
            var red=makeCircle(redX,redY,'red',true,0);
            red.on('dragend',function(){
                var red=this;
                var rx=this.x();
                var ry=this.y();
                stage.find(".blue").each(function(b){
                    var dx=rx-b.x();
                    var dy=ry-b.y();
                    if(dx*dx+dy*dy<radius*radius){
                        b.name('gold');
                        b.fill('gold');
                        red.hide();
                        $last.text("Last covered circle had value="+b.value);
                    }
                });
                layer.draw();
            });
            red.target=blue;
            var text=new Kinetic.Text({
                x:blueX+20,
                y:blueY-5,
                text:value,
                fill:'black',
            });
            layer.add(text);
            layer.draw();
        }
    
    
        function makeCircle(x,y,color,isDraggable,value){
            var circle = new Kinetic.Circle({
                name:color,
                x:x,
                y:y,
                radius:radius,
                fill:color,
                stroke: 'black',
                strokeWidth:2,
                draggable:isDraggable
            });
            circle.value=value;
            layer.add(circle);
            return(circle);
        }
    
    
    }); // end $(function(){});
    
    </script>       
    </head>
    <body>
        <h4 id=lastHit>Drag red to blue.</h4>
        <div id="container"></div>
    </body>
    </html>