javascriptdom-eventskineticjs

KineticJS Setting a Variable Value On an Event


I define several kineticJS circles in an object and create and display several of those objects. What I want is to generate an XML object based on the ones the user selects out of the displayed circles.

For this I tried to set a variable value defined in the object when clicked on a particular circle and call it by an object.property kind of a way. However, this doesn't work.

Following is some of the code I used for the job:

    function Graph(i, j, refRel, refRelTxt) {

        subNodes = seventeen + eighteen + nineteen;
        graphNode = "<" + refRelTxt + ">" + subNodes + "<" + refRelTxt + ">";


        var layer = new Kinetic.Layer({
            width: 200,
            height: 100,
            x: (stage.getWidth() / 2.5) + i,
            y: (stage.getHeight() / 2.5) + j

        });


        var circle19 = new Kinetic.Circle({
            x: 10,
            y: layer.getHeight() / 2,
            radius: cradius,
            fill: '#CCCCCC'
        });

        //++++++++++++++++++++++++++++++++++++++++++++++++++     

        var circle18 = new Kinetic.Circle({
            x: 10 + n,
            y: (layer.getHeight() / 2) - m,
            radius: cradius,
            fill: '#CCCCCC'
        });

        var circle17 = new Kinetic.Circle({
            x: 10 + n,
            y: (layer.getHeight() / 2) + m,
            radius: cradius,
            fill: '#CCCCCC'
        });


        //============Mouse in/out operations


        circle17.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            seventeen = "<node>seventeen<node>";
        });

        circle18.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            eighteen = "<node>eighteen<node>";
        });

        circle19.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            nineteen = "<node>nineteen<node>";;
        });


        // add the shape to the layer
        layer.add(circle19);
        layer.add(circle18);
        layer.add(circle17);

        stage.add(layer);
    }

Create some graph objects like the following:

    var graph19 = new Graph(-(4*hdist), (0*vdist),"circle19","nineteen");

And then call the graph19.graphNode value to get the xml out based on the circles the user has clicked. However, graph19.graphNode doesn't get set with the values dynamically. I know I am doing something wrong here that I cannot figure out. When I set global variables and do this it works. What I want is to extract the xmls form the various Graph objects that are created.


Solution

  • If I understand correctly... you want to be able to call graph19.graphNode and it will output some pre-defined xml string that is dynamically populated depending on which circles the user clicked.

    If so:

    First off, to be able to call the property graphNode from a new Graph object, you have to assign this.graphNode instead of just graphNode by itself. Otherwise when you call graph19.graphNode it will be undefined.

    Then you need to assign this to a variable like: var node = this; so that you can access node within the click function. (This is because by default, when you use this inside a Kinetic event function, click in this case, this will be assigned to the Kinetic.Shape you are binding the event to)

    Finally, you need to update node (this.graphNode) every time you click a circle, use an array to keep track of the elements selected:

        this.graphNode = '';
        var node = this;
        var nodeText = '';
    
        circle17.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            seventeen = "<node>seventeen<node>";
            nodeText += seventeen;
            node.graphNode = "<" + refRelTxt + ">" + nodeText + "<" + refRelTxt + ">";
        });
    
        circle18.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            eighteen = "<node>eighteen<node>";
            nodeText += eighteen;
            node.graphNode = "<" + refRelTxt + ">" + nodeText + "<" + refRelTxt + ">";
        });
    
        circle19.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            nineteen = "<node>nineteen<node>";
            nodeText += nineteen;
            node.graphNode = "<" + refRelTxt + ">" + nodeText + "<" + refRelTxt + ">";
        });
    

    The reason your code wasn't working was because you've defined

    subNodes = seventeen + eighteen + nineteen;

    Before seventeen eighteen and nineteen have even been defined (since they are defined when the user clicks on the the respective Kinetic.Circle

    Also, as a suggestion I recommend that instead of creating a new Kinetic.Layer and adding it to the stage every time you call your Graph function, you might want to create a new Kinetic.Group instead and add that to the layer. See here for more information: What are the differences between group and layer in KineticJs

    UPDATE

    Okay if you need to deselect the objects as well, we'll need to keep track of which objects are selected in an array. Then we can use that array to determine how this.graphNode will be populated.

    Something like this (note I haven't tested this code..):

        this.graphNode = '';
        this.selectedNodes = [];
        this.nodeText = '';
        var node = this;
    
        circle17.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            seventeen = "<node>seventeen<node>";
            selectedNodes.push(seventeen);
            node.nodeText = '';
            for (var i=0; i<selectedNodes.length; i++) {
              node.nodeText += selectedNodes[i];
            }
            node.graphNode = "<" + refRelTxt + ">" + node.nodeText + "<" + refRelTxt + ">";
        });
    
        circle18.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            eighteen = "<node>eighteen<node>";
            selectedNodes.push(eighteen);
            node.nodeText = '';
            for (var i=0; i<selectedNodes.length; i++) {
              node.nodeText += selectedNodes[i];
            }
            node.graphNode = "<" + refRelTxt + ">" + node.nodeText + "<" + refRelTxt + ">";
        });
    
        circle19.on('click', function (evt) {
            this.setFill('#00FF00');
            layer.draw();
            nineteen = "<node>nineteen<node>";
            selectedNodes.push(nineteen);
            node.nodeText = '';
            for (var i=0; i<selectedNodes.length; i++) {
              node.nodeText += selectedNodes[i];
            }
            node.graphNode = "<" + refRelTxt + ">" + node.nodeText + "<" + refRelTxt + ">";
        });
    

    After this you can do something similar to remove the object from the selectedNodes array on dblclick event.