【IT168专稿】如果你不使用Visual Studio .NET或微软Expression Studio,你可能认为Silverlight不会对你有什么帮助。但是作为一个PHP开发者,通过在合适的地方使用合适的语法,你会取得令自己都惊讶的成功。这可能需要你反复试验,但是你的确能够为你的PHP应用增加一些Silverlight的华丽,并且无需使用任何微软的IDE工具。
在本文示例中,你看到一个组合使用了PHP、XAML和JavaScript的简单Silverlight应用,而且看不到一点.NET代码。它将让你体验Silverlight的潜力。我们将从一个简单的PHP菜单入手,然后使用自己喜爱的文本编辑器创建一个“Hello,World”类Silverlight应用。一旦完成上述任务后,你可以非常快速的将两者融合,产生一个Silverlight应用,最后通过一些小修改使其更有趣。
步骤一:经典的PHP菜单
出于演示需要,我们将创建一个“准动态”菜单,我们将使用一个简单的数组来替代创建一个内容数据库。首先,创建一个名为PHPMenu.php的页面:
<head>
<title>Silverlight PHP Menu</title>
<style type="text/css">
.navMenu {
height: 300px;
width: 400px;
}
</style>
</head>
<body>
<p>Just PHP:</p>
<div id="navMenuPlain" class="navMenu">
<?
// This is where you would do a fetch
$menu=array('Home','Links','About','Contact');
$n = 0;
foreach ($menu as $m) {
$n++;
echo('<h2>' . $m . '</h2>');
}
?>
</div>
</body>
</html>
运行该页面,将看到如下图所示的效果:
图1
步骤2:Hello,Silverlight
现在我们把目光转移到创建一个简单的Silverlight应用上。如果你使用某些工具来创建Silverlight应用的话,诸如Express Studio和Visual Studio .NET,你将发现几件事情:
•创建一个新项目时将自动创建整个工程目录架构,包括可执行代码。
•你将能够发布该项目到不同目的地,包括本地,但产品目录架构也会自动为你创建。
•无论是项目文件,还是目录架构,都不是你希望创建的东西。
关于最后一点:最新版的Visual Studio和Silverlight的格式已经与最初有了很大差别。举例来说,现在项目把所有必需的代码和组件捆绑到.xap文件中,以提高性能和简化部署。幸运的是,创建Silverlight项目的一个老技术依然可以使用,而且在创建本文中Silverlight应用类型时非常方便。
从根本上来说,创建一个Silverlight应用,你真正需要的有4个文件:
•Silverlight.js-创建Silverlight组件的一个辅助文件。只要你开始一个新的Silverlight项目,它就会自动被创建。
•Landing Page-存放Silverlight对象的页面。过一会儿,它将变成PHPMenu.php。
•Javascript Page-它一般被包含在Landing Page中,但更方便的是作为一个独立文件。
•XAML文件-这是Silverlight插件解释的对象。它通常是由Expression Blend、Visual Studio或其它第三方应用所创建。它是为我们的PHP应用增加Silverlight功能的关键,当然这并不意味着它必须是一个.xaml文件,只要该文件使用了合适的XAML语法即可。
首先来看一下landing page。在步骤3中以下代码将与PHPMenu.php结合,现在让我们先创建一个名为HelloSilverlight.htm的文件:
<head>
<title>Silverlight PHP Menu</title>
<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="xamlFunctions.js"></script>
</head>
<body>
<p>Silverlighted PHP:</p>
<div id="navMenuSL" class="navMenu">
<script type="text/javascript">
createNavMenu();
</script>
</div>
</body>
</html>
接下来,创建javascript。它将探测Silverlight插件并创建一个委托,然后创建在.htm文件中使用的Silverlight对象。当然,你也可以直接在刚刚创建的html页面中直接这样做。我们把这个文件称为xamlFunctions.js:
{
Silverlight.createObjectEx({
source: "hello.xaml",
parentElement: document.getElementById("navMenuSL"),
id: "slNavMeu",
properties: {
width: "100%",
height: "100%",
inplaceInstallPrompt:true,
version: "3.0"
}
});
}
if (!window.Silverlight)
window.Silverlight = {};
Silverlight.createDelegate = function(instance, method) {
return function() {
return method.apply(instance, arguments);
}
}
最后,创建XAML文件,并在以上代码中作为“源”来引用它。一会儿它将变成一个PHP文件,来方便提供某些动态菜单选项。另外正如我们所提到的,这些代码通常使用一个设计工具来创建。手动处理XAML代码是一件非常复杂的事情。一方面调试非常困难,错误的原因可能是我们的XAML中存在一个空格;而且供我们使用的控件将非常有限。许多控件目前处于测试阶段,尤其是那些在版本3和版本4中增加的空间更是如此,需要程序集来实例化。不过不用担心,通过下面的例子可以让我们有基础创建更复杂的东西。我们把这个文件称为hello.xaml:
<Canvas HorizontalAlignment="Left" Margin="0,0,0,0" Width="300" Height="400" VerticalAlignment="Top">
<Rectangle x:Name="Rect0" Fill="#FF5A2191" Height="40" Canvas.Left="20" RadiusY="15" RadiusX="15" Opacity=".5" Stroke="Black" Canvas.Top="0" Width="150" >
</Rectangle>
<TextBlock Foreground="#FFF7F1F1" Canvas.Top="10" Canvas.Left="45" Text="Hello, Silverlight!" />
</Canvas>
</Grid>
关于这段代码需要注意的是:
•嵌套:Silverlight使用了不同的容器,诸如Grid、Canvas和StackPanel。
•分层:因为Rectangle控件没有Text属性,我们需要创建一个单独的TextBlock,并设置它们各自的Canvas.Top属性,这样它们可以被正确的安排。控件被嵌套在画布上的方式就是它们显示的方式。
•透明度:控件的透明度是一个从0到1的double类型数值。本文例子中控件的透明度值是0.5。
•RadiusX/Y:这是XAML非常有趣的一个地方。通过简单的修改Radius属性,我们可以把一个矩形的拐角圆弧化。由于这些属性可以通过JavaScript设置,我们可以动态的对它们进行修改。
现在打开我们的新HelloSilverlight.htm页面。(记得把Silverlight.js放在相同的目录。)我们将看到类似下图的网页:
图2
在开始第三步之前,对我们的XAML文件进行一个小小的修改。这是Silverlight开始显现其强大之处的开始。通过增加三行代码,我们的控件就能够具有漂亮的阴影效果,在过去实现这一点可能要编写长长的代码和图形处理。
在我们代码中的
<DropShadowEffect/>
</Rectangle.Effect>
效果如下:
图3
步骤3:将两者合二为一
现在是我们将PHP菜单和Silverlight应用进行融合的时候了。在登录页面中,将HelloSilverlight.htm的内容加入到PHPMenu.php中,得到如下代码:
<head>
<title>Silverlight PHP Menu</title>
<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="xamlFunctions.js"></script>
<style type="text/css">
.navMenu {
height: 300px;
width: 400px;
}
</style>
</head>
<body>
<p>Just PHP:</p>
<div id="navMenuPlain" class="navMenu">
<?
// This is where you would do a fetch
$menu=array('Home','Links','About','Contact');
$n = 0;
foreach ($menu as $m) {
$n++;
echo('<h2>' . $m . '</h2>');
}
?>
</div>
<p>Silverlighted PHP:</p>
<div id="navMenuSL" class="navMenu">
<script type="text/javascript">
createNavMenu();
</script>
</div>
</body>
</html>
接下来,在我们的xamlFunction.js文件中,需要做一个小小的调整:使用“createMenu.php”替代“hello.xaml”。正如前面提到的,我们的XAML源并不需要是一个.xaml文件。
现在创建一个名为createMenu.php的新文件:
<Canvas HorizontalAlignment="Left" Margin="0,0,0,0" Width="300" Height="400" VerticalAlignment="Top">
<?
//Database fetch goes here
$menu=array('Home','Links','About','Contact');
$n = 0;
foreach ($menu as $m) {
echo('<Rectangle x:Name="Rect' . $n . '" Fill="#FF5A2191" Height="40" Canvas.Left="20" RadiusY="15" RadiusX="15" Opacity=".5" Stroke="Black" Canvas.Top="' . ($n * 40) . '" Width="150" MouseEnter="mouseEntered" MouseLeave="mouseLeft">');
echo('<Rectangle.Effect><DropShadowEffect/></Rectangle.Effect>');
echo('</Rectangle>');
echo('<TextBlock Foreground="#FFF7F1F1" Canvas.Top="' . (($n * 40) +10) . '" Canvas.Left="45" Text="' . $m . '" />');
$n ++;
}
?>
</Canvas>
</Grid>
如上所示,除了某些明显的区别之外,实质上以上代码与hello.xaml大体相同。在这里我们不是通过动态列表来实现迭代,而是使用了一个数组。增加了一个小计数器来处理定位功能、
有人可能注意到还增加了“MouseEnter”和“MouseLeave”事件。一会儿后我们将看到它们的效果。
运行PHPMenu.php我们将看到的界面如下:
图4
首先,界面从上世界90年代中期风格的导航菜单变成90年代末期风格的按钮,而且一切都是通过XAML和Silverlight动态创建的。而且更重要的是,所有都是高度可控的,通过JavaScript可以迅速的设定或修改其属性。
步骤四:增加动画
XAML一个非常智能的地方是能够让开发者增加资源到嵌入层,尤其是Storyboad。在Silverlight中,通过一个Storyboad设定一个数值范围给特定控件的特定属性。通过定位和命名特定属性,我们可以修改控件的透明度,填充其颜色,甚至移动该控件。
不过,要想得到自己想要的效果可能要经过反复尝试,因为某些属性并不像人们所预料的那样活动。举例来讲,Silverlight.net的Quickstarts包含了一些不错的初学者示例程序,来演示一个画布的不同动作,其中包括修改画布本身的颜色:http://www.silverlight.net/learn/quickstarts/animations/。但是,即便借助于像Visual Studio这样具有完整资源的IDE工具对一个矩形应用相同的色彩切换技术,也依然需要大量代码编写工作。
不过,对于本文示例中这样简单的应用你依然可以实现某些漂亮的效果。现在就让我们开始动手,打开createMenu.php,然后在开始的下面和PHP脚本的上面增加以下代码:
<Storyboard x:Name="fadeIn">
<DoubleAnimation x:Name="fadeInDouble" Storyboard.TargetProperty="Opacity" Storyboard. Storyboard.TargetName="Rect1" To="1" Duration="0:0:1" />
</Storyboard>
<Storyboard x:Name="fadeOut">
<DoubleAnimation x:Name="fadeOutDouble" Storyboard.TargetProperty="Opacity" Storyboard. Storyboard.TargetName="Rect1" To=".5" Duration="0:0:1" />
</Storyboard>
</Canvas.Resources>
关于该代码的注意事项如下:
注意该容器是Canvas.Resources。Storyboards无论在哪个容器中都被看作一个资源。举例来讲,如果这是一个StackPanel,我们就应该使用StackPanel.Resources。Storyboard应给被命名,这样它才可以被调用程序来引用。
在Storyboard内,实际动画效果基于被修改参数的值类型。本例将修改矩形的透明度。而Opacity是一个double类型数值,因此这儿使用“DoubleAnimation”。另外,动画本身也应该被命名,这样它以后可以被引用。
在动画标签内部,我们使用了一个TargetProperty,在本例中它是“Opacity”,另外还使用了一个TargetName,指向了属性的所有者,在这儿是“Rect1”。
我们可以同时使用“To”和“From”来建立效果的范围。举例来说,从“.5”到“1”会导致该控件从半透明到完全不透明。通常情况下我们可能希望设变化范围的两个边界。但在本文示例中没有设定From边界的值,这样可以实现更平滑的变色效果,因为其默认值是当前值。换言之,当我们开始MouseEnter动画后,控件透明度变到.75,然后MouseLeave动画将从.75变到.5。
我们还可以设定动画的持续时间,格式为H:M:S格式。本例中设定的持续时间是1秒。
在该动画被定义后,我们依然需要触发它们。那么就打开我们的xamlFunction.js文件,并在下面增加如下代码:
{
sender.findName("fadeIn").Begin();
}
function mouseLeft(sender, mouseEventArgs)
{
sender.findName("fadeOut").Begin();
}
如上所示,在找到目标Storyboard后开始执行其中的所有动画。
重新加载PHPMenu.php,并尝试鼠标滑过我们的紫色按钮,将看到一些平滑变色的效果。不过目前这种效果仅在按钮上有,为了让每个控件都有动画效果,还需要做更多的工作。幸运的是,微软对Silverlight引擎增加了一些修改,使得参数可以在JavaScript内更容易的被引用。
function mouseEntered(sender, mouseEventArgs)
{
sender.findName("fadeIn").Stop();
sender.findName("fadeInDouble")["Storyboard.TargetName"] = sender.Name;
sender.findName("fadeIn").Begin();
}
function mouseLeft(sender, mouseEventArgs)
{
sender.findName("fadeOut").Stop();
sender.findName("fadeOutDouble")["Storyboard.TargetName"] = sender.Name;
sender.findName("fadeOut").Begin();
}
两个重要的地方是:
•在对一个新目标设定动画之前,我们需要停止当前目标的动画。
•TargetName的父是动画而非Storyboard。一旦动画被设定到一个新目标,我们可以再次打开Storyboard。
尝试运行PHPMenu.php。我们将看到一些漂亮的鼠标悬停动画,从半透明到全不透明的渐变效果。
利用前面提到的4个基本文件,我们已经快速创建了一个动态菜单,并为其增加一些简单但优雅的悬停动画效果。记住我们刚才创建的一切都是可以通过参数进行调整的:控件的类型、它的大小、颜色、阴影、形状和阴影的方向等。
通过组合XAML和JavaScript,我们能够为自己的PHP应用增加Silverlight效果,而且不用使用任何额外的开发工具。由此不难看出,Silverlight确实能够为PHP应用带来新的东西。