Search code examples
javascripthtml5-canvaskineticjs

How to pass an event on to the nodes below in kinetics


question that is very similar but answer doesn't work in my situation

I have a circle and I want to pass the click event to any objects that are underneath it.

I have tried:

setting cancelbubble to false. setting the cirle layer to listening= false doesn't work for me because the circle is then no longer draggable.

I have made a fiddle here

  var stage = new Kinetic.Stage({
    container: 'container',
    width: 578,
    height: 400
  });
  var layer = new Kinetic.Layer();
  var background = new Kinetic.Layer();

    var colorPentagon = new Kinetic.RegularPolygon({
      x: 80,
      y: stage.getHeight() / 2,
      sides: 5,
      radius: 70,
      fill: 'red',
      stroke: 'black',
      strokeWidth: 4,
      draggable: true
    });
    colorPentagon.on('click', function(evt){ alert("pentagon");});

    var linearGradPentagon = new Kinetic.RegularPolygon({
      x: 360,
      y: stage.height()/2,
      sides: 5,
      radius: 70,
      fillLinearGradientStartPoint: {x:-50, y:-50},
      fillLinearGradientEndPoint: {x:50,y:50},
      fillLinearGradientColorStops: [0, 'red', 1, 'yellow'],
      stroke: 'black',
      strokeWidth: 4,
      draggable: true
    });
    linearGradPentagon.on('click', function(evt){ alert("pentagon");});

    var radialGradPentagon = new Kinetic.RegularPolygon({
      x: 500,
      y: stage.height()/2,
      sides: 5,
      radius: 70,
      fillRadialGradientEndRadius: 70,
      fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'blue'],
      stroke: 'black',
      strokeWidth: 4,
      draggable: true
    });
    radialGradPentagon.on('click', function(evt){ alert("pentagon");});

    background.add(colorPentagon);
    //background.add(patternPentagon);
    background.add(linearGradPentagon);
    background.add(radialGradPentagon);
    stage.add(background);


  var hideCircle = new Kinetic.Circle({
    x: stage.width()/2,
    y: stage.height()/2,
    radius: 650,
    stroke: 'black',
    strokeWidth: 1000,
      draggable:true
  });

 hideCircle.on('click', function(evt){ alert("click");});


  // add the shape to the layer
  layer.add(hideCircle);

  // add the layer to the stage
  stage.add(layer);

Currently to get it to work I have to take the click coordinates and do my own detection. It works but I was hoping for something more elegant.


Solution

  • Here's how to pass your click event to the bottom layer nodes:

    • You can listen for clicks on the stage

    • Determine if the click is inside any node on the bottom layer

    • If the click was inside a node, fire the click event on that node.

    Here's example code and a Demo: http://jsfiddle.net/m1erickson/sFX8y/

    stage.on('contentClick',function(e){
    
        // get the mouse position
        var pos=stage.getPointerPosition();
    
        // fetch the node on the bottom layer that is under the mouse, if any.
        var hitThisNode=background.getIntersection(pos);
    
        // if a node was hit, fire the click event on that node
        if(hitThisNode){
            hitThisNode.fire("click",e,true);
        }
    });