mitnk
mitnk

Reputation: 3307

About Event Listen of Kinetic JS

Below is the code. My expectation is when I hover on the circles, they should show "Circle 0" and "Circle 1" respectively. But they all show "Circle 1".

Why is this and How to fix it.

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <div id="container"></div>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.2.min.js"></script>
    <script defer="defer">
      function writeMessage(message) {
        text.setText(message);
        layer.draw();
      }
      var stage = new Kinetic.Stage({
        container: 'container',
        width: 578,
        height: 200
      });
      var layer = new Kinetic.Layer();
      var text = new Kinetic.Text({
        x: 10,
        y: 10,
        fontFamily: 'Calibri',
        fontSize: 24,
        text: '',
        fill: 'black'
      });

      for (var n=0; n<2; ++n)
      {
          var circle = new Kinetic.Circle({
            x: 100 + n * 100,
            y: stage.height()/2,
            radius: 30,
            fill: 'red',
            stroke: 'black',
            strokeWidth: 4
          });
          var txt = 'Circle ' + n;
          circle.on('mouseover', function() {
            writeMessage(txt);
          });
          circle.on('mouseout', function() {
            writeMessage('');
          });
          layer.add(circle);
      }

      layer.add(text);
      stage.add(layer);
    </script>
  </body>
</html>

Upvotes: 0

Views: 56

Answers (1)

Paul D.
Paul D.

Reputation: 2022

This is not a problem with Kinetic, it's related to JavaScript closures.

You're defining a function in a loop here:

for (var n=0; n<2; ++n) {
  ...
  var txt = 'Circle ' + n;
  circle.on('mouseover', function() {
    writeMessage(txt);
  });
  ...
}

The variable txt is not copied when you declare your function. The problem is that when your anonymous function gets called, the value of txt is 'Circle 1' (because the for has finished and txt was modified during the loop).

You'll need an intermediate function:

var displayMessage = function (circleNumber) {
  var txt = 'Circle ' + circleNumber;
  return function () {
    writeMessage(txt);
  };
};

and your event binding is now :

circle.on('mouseover', displayMessage(n));

See this fiddle: http://jsfiddle.net/GApn7/

If you want to read more on what happens, read this post: How do JavaScript closures work?

Upvotes: 1

Related Questions