Introduction to Scripting

出自OpenFace

跳转到: 导航, 搜索

Prev                                                                           Next

                                第九章  脚本介绍

                                第二部分 教程介绍



目录

简介

  lzx应用程序可以包含程序代码,阅读第2章和发布的XML标签。

在LZX程序中,脚本可以存在:

  * <script>标签中间

  * <method>标签中间

  * 存在引号中间作为属性的值

<script>标签

  把脚本放在<script>中是运行最快的方式。代码在<script>标签中会被立即执行。<script>标签只能嵌入在<canvas>标签下。

  在下面的程序中,注意Debug.write是在log文件中打印了调试信息。

Example 9.1. Using the debugger

<canvas width="500" height="200">  
   <script> <![CDATA[
      Debug.write("hello world");
   ]]></script>
</canvas>


  现在可以利用我们所学的JavaScript知识去创建脚本:

Example 9.2. Incorporating JavaScript

<canvas width="500" height="200">
   <script> <![CDATA[
      var someStr = "Hello , World!"
      Debug.write("@@"+someStr);
      var first = 4;
      var second = 3;
      var result = first + second;
      Debug.write("@@"+result);
   ]]></script>
</canvas>

Javascript

  如果您之前从来没有使用过JavaScript,您会因该语言的一些微妙特性而感到惊讶。例如:把这个作为前面程序的一点微小的扩展。

Example 9.3. JavaScript subtleties

<canvas width="500" height="200">
 <script> <![CDATA[
      var someStr = "Hello , World!"
      Debug.write(someStr);
      var first = 4;
      var second = 3;
      var result = first + second;
      Debug.write(result);
      Debug.write(first+" plus "+" is "+first+second);
      var two = 2;
      if (2 == two)
      {
         Debug.write("2 is two");
      }
   ]]></script>
</canvas>

  除了"4 plus 3 is ..."这行,其它一切都明白。4+3等于7,同样上面的也都是正确的,对不对?

  文档不会为JavaScript提供一个完整的参考。后面的章节会在JavaScript中对专业的知识进行解释,不过,我们建议您使用LZX时有一个JavaScript作为参考。

XML 在脚本中的特点

  我们试用一个简单的 "for" 循环:

Example 9.4. XML characters cause errors

<canvas height="80" width="500">
 <-- the following code will not compile because of the angle bracket -->
 <script><![CDATA[      
   for (var i = 0; i < 11; i++) {
     Debug.write(i);
   }
 ]]></script>
</canvas>

     由于LZX是基于XML 的语言,标签中内容的合法性是存在一定规则的(特别是在<script> 标签中)。"<"字符在‘for’循环中会出现问题。我们不允许在LZX标签中使用‘<’,‘>’字符。

  幸好有办法解决这个问题

注意:

  下面两个例子不是交互的,但第一个LZX程序运行时会出现编译错误,第二个则是正确的lzx程序。

Example 9.5. Encoding XML characters

<canvas height="120">
  <script>
    for (var i = 0; i < 11; i++) {
      Debug.write(i);
    }
  </script>
</canvas>

Example 9.6. Using CDATA

<canvas height="120">
  <script>
    <![CDATA[
    for (var i = 0; i < 11; i++) {
      Debug.write(i);
    }
    ]]>
  </script>
</canvas>

  在实际应用中, CDATA方法对大量的模块代码更实用。

函数

可以在<script>标签中写函数:

Example 9.7. Javascript functions

<canvas height="200" width="500">
 <script> <![CDATA[
    function writeAWord(someWord) {
     Debug.write("@@:"+someWord);
   }   
   writeAWord("HELLO!");
   ]]></script> 

</canvas>

     函数在lzx 文件中是全局的,就象在JavaScript中遵循同样的域规则。

使用脚本操作属性

  下面的例子是介绍如何使用脚本操作view 的属性。

Example 9.8. Manipulating <view> attributes

<canvas width="500">
  <view x="100" y="30" id="view2" width="150" height="30" bgcolor="red">
  <text>This is the second view.</text>
</view>
<view x="20" y="20" width="150" height="30" bgcolor="green">
  <text oninit="LzFocus.setFocus(this)">Press any key to change 'x'.
      <handler name="onkeydown" reference="LzKeys">
          view2.setAttribute('x',200);
      </handler>
  </text>
</view>
</canvas>

  我们也使用了setAttribute() 方法。它使用两个参数:要设置的属性,要给该属性设置的值。

  接下来,我们把View2移走来看看它的后面是什么。我们要计算出第二个view在哪里,然后每按键一次给它增加一定的增量。再看一下APIreference文档中LzView 类的相关内容,我们可以发现 getAttribute() 方法可以得到'x' 属性值。


Example 9.9. getting attributes

<canvas width="500">
  <view x="0" y="0" id="view2" width="150" height="30" bgcolor="red">
   <text>This is the second view.</text>
 </view>
 <view x="20" y="20" width="150" height="30" bgcolor="green">
   <text oninit="LzFocus.setFocus(this)">Press keybord.
       <handler name="onkeydown" reference="LzKeys" args="k">
          var key=k.intValue();
          if(key==13) view2.setAttribute('x',parseFloat(view2.getAttribute('x'))+200);
          else if(key==37) view2.setAttribute('y',parseFloat(view2.getAttribute('y'))+200);
       </handler>
   </text>
 </view>
</canvas>

  那样是可行的,但代码有点凌乱。为此 我们可以写一个函数:

Example 9.10. Moving view by function call

<canvas width="500" height="200">
<script><![CDATA[
   // Moves the second view twenty pixels to the right
  function moveView() {
     var increment = 20;
     var originalX = parseFloat(view2.getAttribute('x'));
     var newX = originalX + increment;
     view2.setAttribute('x', newX);
   }
  ]]></script>
   <view x="0" y="30" id="view2" width="150" height="30" bgcolor="red"/>
   <view x="20" y="20" width="150" height="30" bgcolor="green"/>
   <text oninit="LzFocus.setFocus(this)">This is the second view.
      <handler name="onkeydown" reference="LzKeys">
            moveView();
      </handler>
   </text>
</canvas>

  注意我们是怎么使用'canvas.'语法来指向第二个view的。我们必须完全控制view。代码很容易理解,我们可以把它分成几行,分析并赋给适当的名字变量。

  尽管如此,这个函数被text恰当的分开。打到同样效果的更好的方式是给text写一个方法。

Example 9.11. From function to method

<canvas width="500" height="200">
   <text name="windowTwo">This is the second window.</text>
   <text text="My button" oninit="LzFocus.setFocus(this)" >
     <method name="moveWindow">
       var increment = 20;
       var originalX = parseFloat(this.parent.windowTwo.getAttribute('x'));
       var newX = originalX + increment;
       this.parent.windowTwo.setAttribute('x', newX);
     </method>
     <handler name="onkeydown" reference="LzKeys">
           this.moveWindow();
      </handler>
</canvas>

  由于方法不是全局的,我们必须间接调用。在触发键盘时,我们使用this.moveViewe()。   理论上我们可以再用一个text,当初始的时候会调用第一个text的方法。唯一的区别就是寻址方式。在深入使用方法之前,我们适当的看看寻址方式。

寻址

  在LZX中,对象可以通过name,id 被访问.name属性只能局部访问。因而同一文件可以有多个view 同名(它们不一定是同一深度).id是全局的,所以同一个LZX文件中不能有相同id的view。

  回想一下一个text访问另一个text的方法的例子。

Example 9.12. One text calls another's method

<canvas width="500" height="200">
 <view x="20" y="20" width="210">
  <simplelayout axis="x" spacing="4"/>
  <text text="My Text1" id="Text1" oninit="this.moveView()">
    <handler name="onkeydown" reference="LzKeys" args="k"> 
       var key=k.intValue();
       if(key==13) this.moveView();
       else LzFocus.setFocus(this.parent.text);
    </handler>
    <method name="moveView">
      var increment = 20;
      var originalX = parseFloat(canvas.view2.getAttribute('x'));
      var newX = originalX + increment;
      canvas.view2.setAttribute('x', newX);
    </method>
  </text>
  <text text="My Text2" name="text2">
     <handler name="onkeydown" reference="LzKeys" args="k"> 
       var key=k.intValue();
       if(key==37) Text1.moveView();
       else LzFocus.setFocus(Text1);
    </handler>
  </text>
</canvas>

  两个text都可以使view移动。由于view2在移动,何不使这个方法成为view的内部方法,让两个text都指向它?我们可以通过使用全局变量id访问,而不再使用canvas.语法访问这个method。


Example 9.13. Using the <ID> tag

<canvas width="500" height="200">
 <view x="100" y="60" id="view2">
   <text>This is the second view.</text>
 </view>
 <view x="20" y="20" width="210">
   <simplelayout axis="x" spacing="4"/>
   <text text="My Text1" id="Text1" oninit="this.moveView()">
     <handler name="onkeydown" reference="LzKeys" args="k"> 
        var key=k.intValue();
        if(key==13) this.moveView();
       else LzFocus.setFocus(this.parent.text);
     </handler>
     <method name="moveView">
       var increment = 20;
       var originalX = parseFloat(view2.getAttribute('x'));
       var newX = originalX + increment;
       view2.setAttribute('x', newX);
     </method>
   </text>
   <text text="My Text2">
      <handler name="onkeydown" reference="LzKeys" args="k"> 
        var key=k.intValue();
        if(key==37) Text1.moveView();
       else LzFocus.setFocus(Text1);
     </handler>
   </text>
 </view>
</canvas>

方法和参数

  在下面的例子中我们的两个text做同一事情。何不让它们做不同的事呢?或许可以把view 分别向左右移动。我们可以再写一个方法把view向左移动,使用同一方法移向两个方向视图更显优雅。就象使用函数,我们可以给方法传递参数。


Example 9.14. methods and arguments

<canvas width="500" height="200">
  <view x="100" y="60" id="view2" >
   <method name="moveView" args="direction"><![CDATA[
     if (direction == "left") {
      var increment = -20;
     } else if (direction == "right") {
       var increment = 20;
     }
     var originalX = parseFloat(this.getAttribute('x'));
     var newX = originalX + increment;
     this.setAttribute('x', newX);
   ]]></method>
   <text>This is the second view.</text>
 </view>
 <view x="20" y="20" width="210" oninit="LzFocus.setFocus(this)">
   <simplelayout axis="x" spacing="4"/>
   <text text="Move Left" />
   <text text="Move Right" />
   <handler name="onkeydown"  reference="LzKeys" args="k">
       var key=k.intValue();
       if(key==37)  view2.moveView('left');
       else if(key == 39) view2.moveView('right');
   </handler>
</view>
</canvas>

    我们可以像使用函数那样给方法传递多个参数:

Example 9.15. Passing multiple arguments to a method

<canvas width="500" height="200">
 <view x="100" y="60" id="view2">
   <method name="moveWindow" args="direction, distance"><![CDATA[
     // decide which direction to go
     if (direction == "left") {
       var increment = -1 * distance;
     } else if (direction == "right") {
       var increment = distance;
     }
     var originalX = parseFloat(this.getAttribute('x'));
     var newX = originalX + increment;
     this.setAttribute('x', newX);
  ]]></method>
   <text>This is the second view.</text>
 </view>
 <view x="20" y="20" width="300" oninit="LzFocus.setFocus(this)">
     <simplelayout axis="x" spacing="4"/>
   <text text="Left 2" />
   <text text="Left 20" />
   <text text="Right 20" />       
   <text text="Right 2" />
   <handler name="onkeydown"  reference="LzKeys" args="k">
       var key=k.intValue();
       if(key==37)  view2.moveWindow('left',2);
       else if(key == 39) view2.moveWindow('right',20);
       else if(key == 38) view2.moveWindow('left', 20);
       else if(key == 40) view2.moveWindow('right',2);
   </handler>
   </view>
</canvas>


                                      Home

Prev                                                                          Next