0

I have managed to dynamically create an array of shapes, and they are nicely placed at different coordinates.

However, when I try to assign an event within that loop, the result of click is always the same. As if the click event is still referencing the last iteration of my loop.

What am I doing wrong? Thanks!

EDIT: Actually, re-produced this behaviour in an isolated environment:

var stage = new Kinetic.Stage({
        container: 'container',
        width: 1024,
        height: 768
    });
    var layer = new Kinetic.Layer();
    singleSegment=40;
    for (var i = 0; i < 4; i++) {
                depth=singleSegment+(singleSegment*i);
                dotLabel = new Kinetic.Text({
                    x: depth,
                    y: depth,
                    text: "test"
                });
                dotLabel.on('click', function(evt){
                    console.log(this.x);
                });
                layer.add(dotLabel);
    }
    stage.add(layer);

How do I add different events to these four labels?

Mahdi Alkhatib
  • 1,954
  • 1
  • 29
  • 43
tonysepia
  • 3,340
  • 3
  • 27
  • 45
  • I'm not the best person to explain javascript closures but wit luck, maybe someone else can. Otherwise you'll have to google around – Jani Hyytiäinen Mar 15 '13 at 18:22
  • @JaniHyytiäinen, it looks like it is a scope problem. But I don't understand what's wrong exactly. I made the code above smaller, so it can be tested anywhere. – tonysepia Mar 16 '13 at 10:44

2 Answers2

2

You are doing everything correct, I think. but because of this;

            console.log(i);

The last value of i is array.length-1, and when it is clicked, it shows that value, which does not change because it's outside of loop when it is clicked.

This will show different value.

            console.log(this.attrs.x);
allenhwkim
  • 27,270
  • 18
  • 89
  • 122
  • Thank you for your answer! But when I add this, I get "undefined" in console. Is that a scope problem? Can I add those shapes to the global object "node", and then access their properties through that? – tonysepia Mar 16 '13 at 10:32
  • I also added a cleaner piece of code, which you coud paste into your html doc. Same result. I use kinetic-v4.3.1-beta2.js – tonysepia Mar 16 '13 at 10:44
1

I just had to deal with this same issue. I solved it by storing to each shape its location.

    for (var axisItem=0;axisItem<innerCircleXAxisArray.length;axisItem++)
        {
            var arc = new Kinetic.Shape({
                drawFunc: function(canvas){
                    var allAttrs = this.getAttrs();
                    var start = allAttrs['start'];
                    var end = allAttrs['end'];
                    var context = canvas.getContext();
                    context.strokeStyle = 'red';

                    var centerOfCanvasX = canvasWidth / 2;
                    var centerOfCanvasY = canvasHeight / 2;

                    context.translate(centerOfCanvasX, centerOfCanvasY);
                    context.lineWidth = 15;
                    context.beginPath();
                    context.arc(0, 0, 284, start , end, true); 
                    canvas.stroke(this); // Fill the path
                    context.closePath();
                    context.translate(-centerOfCanvasX, -centerOfCanvasY);
                },
                fill: 'red',
                stroke: 'red',
                strokeWidth: 15
            });


            arc.setAttrs({'start': innerCircleXAxisArray[axisItem]['start'], 'end': innerCircleXAxisArray[axisItem]['end']});

            layer.add(arc);
        }
        stage.add(layer);

When the object is created, I use setAttrs to store the object's location - a start and end angle since these are arcs, but it could just as easily be an x and y point. Then in the drawFunc I use getAttrs to retrieve that data and to draw the object.

VikR
  • 4,818
  • 8
  • 51
  • 96