Introduction to Scripting
出自OpenFace
第九章 脚本介绍
第二部分 教程介绍
目录 |
简介
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>

