【问题标题】:Change text or color according to dynamically changed variable (KineticJS)根据动态变化的变量(KineticJS)更改文本或颜色
【发布时间】:2013-06-22 09:59:53
【问题描述】:

我有一个Kinetic.Group,并在其属性中添加了变量actualstatusactualstatus 被其他一些 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-property 发生变化时,有没有办法用新颜色等重新绘制形状?或者有没有办法监听actualstatus - 变化?

我希望你能以某种方式了解我上面说的有点复杂的内容:) 当然,非常感谢任何帮助;)

【问题讨论】:

    标签: javascript html html5-canvas kineticjs


    【解决方案1】:

    您可以“监听”“实际状态”的值何时发生变化并相应地改变颜色

    您可以使用 javascript getter 和 setter 来做到这一点。

    这两个函数与属性(实际状态)相关联,并在请求属性值(getter)和分配属性值(setter)时触发。

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

    这样做的重要性在于,您可以使用 setter 函数来更改实际状态值……并且……您还可以触发对形状颜色的更改。

    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中的变量变化!

    这是代码和小提琴: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>
    

    【讨论】:

    • +1 哇,非常感谢!我读过 KineticJS 本身可以监听 shape-attrs-changes(github.com/ericdrowell/KineticJS/wiki/…“新功能”-第二个要点)。但我不知道如何将它用于我的实际状态属性。它适用于rect.on('yChange,function(){});,但不适用于actualstatusChange。我错过了什么吗?
    • 实际上是 javascript 使用 Object.defineProperty 监听实际状态的变化。当 javascript setter 函数同时更改实际状态中的值并且 ALSO(!) 更改任何 Kinetic 形状的颜色时,Kinetic 部分就出现了。我看到 Kinetic 新提供了类似的功能,但纯 javascript setter 运行良好,我还没有尝试过 Kinetic 功能。
    • 我当然明白您正在使用 javascript 进行属性监听,它的效果非常好,但我真的很想与 KineticJS 挂钩并使用它的所有功能。你知道如何使用 KineticJS-attrs-changes-listener 吗?我想我以前用rect.on('yChange'...) 使用过它,但实际状态似乎不是那样工作的......:P
    【解决方案2】:

    @markE 感谢您的帮助和出色的 code-sn-p。我想使用 KineticJS 函数,现在可以通过使用 .setAttrs() 方法设置 activestate 来工作:

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

    如果您使用.setAttrs() 更改属性,您可以使用 KineticJS 提供的 attrs-listener:

    rect.on('activestateChange', function(){
        if(activestate == "1")
             rect.setFill('yellow');
        else if(activestate == "0")
             rect.setFill('grey');
    });
    

    【讨论】:

      猜你喜欢
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      相关资源
      最近更新 更多