根据动态变化的变量改变文本或颜色(KineticJS)

3

我有一个Kinetic.Group,并将变量actualstatus添加到其属性中。 actualstatus会根据一些其他JavaScript动态更改为“1”或“0”(1 = ON 0 = OFF)。 现在,我想要做的事情是使用KineticJS显示实际状态(开或关)。当我使用自定义Kinetic.Shape时,可以这样简单地实现:

var shape = new Kinetic.Shape({
    actualstatus: "",
    drawFunc: function(canvas){
        var ctx = canvas.getContext();
        ctx.beginPath();
        if(this.actualstatus == "1") ctx.fillStyle = "yellow";
        else if(this.actualstatus == "0") ctx.fillStyle = "lightgrey";
        ctx.fillRect(0,0,50,50);
        ctx.closePath();
    }
});

它的功能非常完美,但是无法监听事件并使用多个ctx.beginPath() ctx.closePath()来绘制复杂的小部件。
因此,我正在重新构建它,只使用非自定义Kinetic-Shapes,这解决了我的事件和复杂绘图问题,但现在,它不再根据包含所有形状的组的actualstatus属性更改其颜色或文本。
所以我的问题是:是否有一种方法可以在每次actualstatus属性更改时重新绘制形状以获取新的颜色等?或者是否有一种方法可以监听actualstatus的更改?
希望您可以对我上面有点复杂的说法有所了解:) 当然,任何帮助都将不胜感激;)
2个回答

3
你可以“监听”“actualstatus”的值何时发生变化,然后相应地更改颜色。你可以使用javascript的getter和setter来实现这一点。它们是与属性(actualstatus)相关联的两个函数,每当请求属性值(getter)和分配属性值(setter)时都会触发它们。
// this will trigger the getter function
var test = actualstatus;

// this will trigger the setter function
actualstatus=”1”;

重要的是,您可以使用setter函数更改actualstatus值...并且还可以触发形状颜色的更改。
以下是setter函数的示例:
function (newValue) {

        // change the current value to the new value
        this.currentValue = newValue;

        // and also change the rectangle’s color based on the newValue
        switch(value){
            case "0":
                myKineticRect.setFill('lightgrey');
                break;
            case "1":
                myKineticRect.setFill('yellow');
                break;
            default:
                myKineticRect.setFill('red');
                break;
        }
        layer.draw();    
}

将getter/setter投入使用:

首先,声明一个对象,该对象将包含我们想要“监听”的所有变量。

// create a container object for all the Vars we want to "listen" to
var WatchedVars=function(){};

接下来,告诉WatchedVars添加一个名为“actualstatus”的变量,它将具有getter和setter:

    // "listen" for gets and sets on "actualstatus"
    Object.defineProperty(WatchedVars.prototype,"actualstatus",{

        // this is a "private" property that holds the current value of actualstatus

        privateValue: "X",

        // on get: just return the current value (privateValue)

        get: function(){ return(this.privateValue); },

        // on set: set the current value 
        // ...AND(!)... execute the callback handler (actualstatusSetHandler)

        set:  function(newValue){
                  this.privateValue=newValue;
                  actualstatusSetHandler(this.privateValue);
              }

    });

所以每当您更改actualstatus的值时,setter方法会被调用。
// assigning w.actualstatus a value of "1" triggers its setter function
w.actualstatus=1”;

这个setter会将actualstatus的当前值更改为“1”。

这个setter同时会调用actualstatusSetHandler(),使矩形填充成黄色。

每当actualstatus的值发生变化时,都会执行这个回调函数:

    // this handler will get called every time the value of actualstatus changes
    // in this case, we change the fill color of a kinetic shape (rect)
    function actualstatusSetHandler(value,isTrue){
        switch(value){
            case "0":
                rect.setFill('lightgrey');
                break;
            case "1":
                rect.setFill('yellow');
                break;
            default:
                rect.setFill('red');
                break;
        }
        layer.draw();
    }

这就是如何在javascript中“监听”变量更改的方法!
这里有代码和一个Fiddle:http://jsfiddle.net/m1erickson/Uw4Ht/
<!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-v4.5.1.min.js"></script>

<style>
#container{
  border:solid 1px #ccc;
  margin-top: 10px;
  width:200px;
}
</style>        
<script>
$(function(){

    // create a container object for all the Vars we want to "listen" to
    var WatchedVars=function(){};

    // "listen" for gets and sets on "actualstatus"
    Object.defineProperty(WatchedVars.prototype,"actualstatus",{

        // this is a "private" property that holds the current value of actualstatus

        privateValue: "X",

        // on get: just return the current value (privateValue)

        get: function(){ return(this.privateValue); },

        // on set: set the current value 
        // ...AND(!)... execute the callback handler (actualstatusSetHandler)

        set:  function(newValue){
                  this.privateValue=newValue;
                  actualstatusSetHandler(this.privateValue);
              }

    });

    // this handler will get called every time the value of actualstatus changes
    // in this case, we change the fill color of a kinetic shape (rect)
    function actualstatusSetHandler(value,isTrue){
        switch(value){
            case "0":
                rect.setFill('lightgrey');
                break;
            case "1":
                rect.setFill('yellow');
                break;
            default:
                rect.setFill('red');
                break;
        }
        layer.draw();
    }

    // just normal Kinetic stuff
    // create stage & layer, add a rectangle
    var stage = new Kinetic.Stage({
        container: 'container',
        width: 200,
        height: 200
    });
    var layer = new Kinetic.Layer();
    stage.add(layer);


    var rect = new Kinetic.Rect({
      x: 30,
      y: 30,
      width: 100,
      height: 30,
      fill: "green",
      stroke: "gray",
      strokeWidth: 3
    });    
    layer.add(rect);
    layer.draw();



    // create an instance of WatchedVars
    var w=new WatchedVars();


    // testing...just change the value of actualstatus
    $("#set0").click(function(){  w.actualstatus="0";  });
    $("#set1").click(function(){  w.actualstatus="1";  });


}); // end $(function(){});

</script>       
</head>

<body>
    <div id="container"></div>
    <button id="set0">actualstatus==0</button>
    <button id="set1">actualstatus==1</button>
</body>
</html>

实际上,是JavaScript使用Object.defineProperty监听actualstatus的更改。当JavaScript setter函数同时更改actualstatus的值并且还更改任何Kinetic形状的颜色时,Kinetic部分就会出现。我看到Kinetic新提供了类似的功能,但是纯JavaScript setter的效果非常好,所以我没有尝试过那个Kinetic功能。 - markE
我确信你正在使用JavaScript进行属性监听,它的效果非常好,但我真的想要与KineticJS连接并使用其全部功能。你知道如何使用KineticJS-attrs-changes-listener吗?我猜以前我用过rect.on('yChange'...),但是在实际状态下似乎不像那样工作... :P - irie

1

@markE 谢谢你的帮助和精彩的代码片段。我想使用KineticJS函数,现在通过使用.setAttrs()方法设置activestate已经可以使用了:

rect.setAttrs({
     activestate: "0" //or "1"
});

如果您使用.setAttrs()更改属性,则可以使用KineticJS提供的属性监听器:
rect.on('activestateChange', function(){
    if(activestate == "1")
         rect.setFill('yellow');
    else if(activestate == "0")
         rect.setFill('grey');
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接