[WPF] 手把手教你做“咖啡”按钮
概要:本文将通过WPF按钮与Flash按钮的制作流程的对比讲解如何用Xaml实现按钮动画,同时你也还能学习Expression Blend。本文假设你正在制作一套点饮料的系统,现在你要做的就是制作出一个点咖啡按钮,用户点了之后就会给用户下咖啡订单。当然这样的按钮要越直观越好,要让用户一看就明白这是用来点咖啡的按钮,这就是对这个按钮的要求。
本文使用的开发环境:Expression Blend 2 sp1, Expression Design
阅读本文前建议先阅读《WPF揭秘》中的以下章节,学习一些基础概念:
Xaml,《WPF揭秘》第2章
样式,《WPF揭秘》10.1
控件模板,《WPF揭秘》10.2
触发器,《WPF揭秘》10.1.2
动画和Storyboard,《WPF揭秘》第13章
关键帧,《WPF揭秘》13.3
正文
任何一个学过Flash的人首先学习的内容一般都是按钮的制作,在Flash中按钮有四种状态,即Up(未点击), Over(鼠标悬停), Down(鼠标按下), Hit(鼠标点击)。
如果要为某种状态添加动画,则需要用一个内嵌的MovieClip来实现,当然本文并不是讲解Flash的教程,就不多做介绍了。
很多WPF的初学者觉得Flash似乎比微软的东西好用,因为Flash有ButtonClip,很直观很方便。其实呢,从软件开发角度讲,WPF的事件模型更科学,因为程序中所有的动画、视觉效果都是由事件触发的,在WPF中如果要实现类似Flash中的Up, Down, Over, Hit四种状态也并非难事,你其实很容易找到对应的属性和事件,下面我列出一张表,大家看了就很容易明白了:
Flash
WPF
UpMouseLeftButtonUp (Event)
DownMouseLeftButtonDown (Event)
OverIsMouseOver (Property)
HitIsPressed (Property)
是不是发觉WPF的事件和属性更有针对性,也表达得更清楚些呢?当然我们必须承认Flash有一点做得很好——它把Button所对应的最常用的四种状态放在了一个单独的编辑视图(即ButtonClip编辑器)中,这样初学者很容易上手,也许Expression Blend以后的版本可以借鉴一下。
做任何一样东西,我们必须了解最终我们到底要做什么,所以先来看看效果图:
你是不是有点等不及啦,那我们就开始动手吧!
画图
仔细分析下你会发现其实整个按钮中最关键的还是那个冒着热气的杯子,所以呢,我们先要把杯子画出来,用什么画呢?自然是用Expression Design。
里面画了几个杯子的草稿,搞设计的朋友都知道这其实就是在做Graphics,怎么画不是这篇文章的重点,大家自己揣摩吧。要注意一点,每次画完一个杯子一定要把几个Path放在一个Group中,这样才能保证导出的时候一个Canvas中就是一个杯子的图形,导出的Xaml与下面的代码类似:
--------------
[code=XAML]<Viewbox x:Name="Group" Width="30.8005" Height="32.0573" Canvas.Left="35.6441" Canvas.Top="40.7749">
<Canvas Width="30.8005" Height="32.0573">
<Path x:Name="Path" Width="3.01129" Height="16.1666" Canvas.Left="6.25348" Canvas.Top="2.18024" Stretch="Fill" StrokeThickness="2" StrokeLineJoin="Round" Stroke="#FF898686" Fill="#FF9E9898" Data="F1 M 7.92015,3.18024C 7.56208,5.32863 8.36821,8.0273 8.25348,10.0135C 8.08681,12.899 7.25348,14.8798 7.25348,17.3469"/>
<Path x:Name="Path_0" Width="3.01129" Height="16.1666" Canvas.Left="10.7747" Canvas.Top="2.27339" Stretch="Fill" StrokeThickness="2" StrokeLineJoin="Round" Stroke="#FF898686" Fill="#FF9E9898" Data="F1 M 12.4414,3.27339C 12.0833,5.42178 12.8895,8.12045 12.7747,10.1067C 12.6081,12.9921 11.7747,14.973 11.7747,17.44"/>
<Path x:Name="Path_1" Width="3.01129" Height="16.1667" Canvas.Left="14.8581" Canvas.Top="2.14838" Stretch="Fill" StrokeThickness="2" StrokeLineJoin="Round" Stroke="#FF898686" Fill="#FF9E9898" Data="F1 M 16.5247,3.14838C 16.1667,5.29678 16.9728,7.99545 16.8581,9.9817C 16.6914,12.8671 15.8581,14.848 15.8581,17.315"/>
<Path x:Name="Path_2" Width="10.6739" Height="7.81753" Canvas.Left="19.7414" Canvas.Top="19.929" Stretch="Fill" StrokeThickness="2" StrokeLineJoin="Round" Stroke="#FF898686" Fill="#FFFFFFFF" Data="F1 M 22.9393,21.1666C 25.1893,21.1529 29.1164,20.8922 29.3039,20.9334C 29.8005,21.0424 28.6164,23.7316 26.1476,25.1718C 23.7262,26.5844 23.3768,26.8041 20.7414,26.7355"/>
<Path x:Name="Path_3" Width="24.1439" Height="12.9312" Canvas.Left="0.12096" Canvas.Top="18.8018" Stretch="Fill" StrokeThickness="2" StrokeLineJoin="Round" Stroke="#FF898686" Fill="#FFFFFFFF" Data="F1 M 1.12678,20.5627C 1.48111,19.7491 22.9913,19.4325 23.2518,20.4012C 23.4669,21.2014 21.0644,30.4402 12.6734,30.7251C 2.88443,31.0573 1,20.8539 1.12678,20.5627 Z "/>
</Canvas>
</Viewbox>[/code]
--------------
如上所示,上面5个杯子会被导出成5个Viewbox,里面各有一个Canvas,不过你在Expression Blend中使用时会发现,其实我们只需要Canvas就行了,Viewbox是不用的。
导出Xaml
好了东西画完了,下面我们讲怎么把这些图形导出成Xaml,并放入Expression Blend中。
在File菜单中你会看到Export菜单项,点击它,你会看到下面的对话框:
这里请注意,Format一定要选Xaml WPF Canvas,这样才能够保证导出的Xaml Canvas能够与WPF程序兼容,其他选项都无所谓。
创建WPF应用程序
接下来我们开始使用Expression Blend创建一个简单的应用程序,当然这个程序的主要目的就是帮助我们查看这个按钮的最终效果。
点Expression Blend的File->New Project菜单,弹出下面的对话框:
只要选择WPF Application就可以了,其他所有选项都可以使用默认项。
紧接着从左边的工具栏中拖出一个Button,放进默认的窗口(Window1.xaml)中(随便放哪都成),尺寸大小全看个人喜好,我这里就不给参考值了。
修改控件模板
右键点击这个按钮,点Edit Control Parts (Template) => Edit a Copy,进入控件模板编辑器,类似于Flash的MovieClip编辑器。
这时会弹出一个对话框,询问Button样式的存放位置,建议选This document后面的Window:Window,当然如果你要做应用程序,把样式放到Application中也不失为一个不错的选择,这样便于全局管理样式。
接下来我们要做的步骤很关键,大家别开小差哦!
首先我们把Button的控件模板中的Chrome控件替换为Grid,最简单的办法就是把Grid从工具箱中拖进编辑区域。然后在Grid中加入一个ContentPresenter和Rectangle。
[思考题] 为什么要多加一个Rectangle?(提示,可以对比一下Flash中ButtonClip的制作,原理是一样的)
接下来我们就要用上刚才导出的Xaml了,切换到XAML视图,把第一个Canvas的代码拷贝到当前的Grid下面,回到设计视图,你应该会看到Grid现在有3个1级子节点,分别是rectangle、[ContentPresenter]和canvas,如下所示:
其中我们把rectange的Fill设置为渐变色,代码如下:
[code=XAML]<Rectangle Stroke="#FF000000" HorizontalAlignment="Stretch" Margin="0,0,0,0" x:Name="rectangle">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF8F8F8" Offset="0"/>
<GradientStop Color="#FFD9D9D9" Offset="0.853"/>
<GradientStop Color="#FF5F5E5E" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>[/code]
当然你可以不用在XAML代码中设置,直接在调色器中设置就行了。
如图中的红色框所示,依次点击Properties选项卡=>Fill=>渐变按钮,然后在渐变色编辑器中配置该渐变色。
好了,第一步完成了,此时我们已经能够看到按钮的最终效果了,是不是就结束了?当然没有,我们还要加动画,当鼠标悬停在按钮上时让咖啡冒气,这样这个咖啡按钮才会更逼真。
制作动画效果
按F6切换到动画模式。
在Triggers框中点 +Property (添加属性触发器),然后把默认的 IsCancel改成IsMouseOver,把=后面的值改成True(如果改不了,可以到XAML视图中修改),如下所示:
你会注意到IsMouseOver左侧有一个红色的按钮,这表示正在录制动作。接下来在Objects and Timeline框中点+按钮,新建一个Storyboard,然后就可以开始录制动画了。Flash中做动画默认是有帧的,所有的动画都是基于Timeline中的帧去实现的,要改变动画状态则可以用关键帧,微软也借鉴了这方面的经验,WPF中也有关键帧的概念。要添加关键帧,可以点时间左边的 按钮,所有关键帧添加完毕后的效果如下所示:
在添加这些关键帧的时候要注意一点,由于我们的动画不需要连续的改变,是独立的,所以我们必须告诉WPF我们的用意,而对每个关键帧设置Hold In就可以解决这个问题,只需要右击某个关键帧就可以看到该选项。至于烟怎么摆动全凭个人喜好,不过我总觉得我自己做的烟似乎机械化了点,呵呵,毕竟不是搞美工出生的。
大家都知道,在Flash中所有的关键帧默认是不会做连续值渐变的,除非你使用补间动画(Motion Tween), 右图便是一个使用Flash补间动画的例子。
让按钮动起来
做完了Storyboard之后,有些人肯定很兴奋,迫不及待地把程序跑了起来,结果却很失望,鼠标移动到按钮上一点动静都没有,其实原因很简单——Storyboard没有与相应的触发器建立联系。回到刚才的Triggers框,点IsMouseOver=true,在出现的actions when activating和actions when deactivating中分别添加Storyboard Begin和Storyboard Stop动作。
好了,现在你可以运行程序了,鼠标放上去便能看到烟的效果。
下载完整程序代码请点这里:CoffeButtonSample.zip
[课后作业]:举一反三,制作一个挖金矿游戏中的Play按钮。
要求:
1. 按钮要有质感,绘制时要加入一定的反光面
2. 鼠标没有移上去的时候,会每隔一定时间发出一道金光,这道光从左向右移动,如中间一张图所示
3. 鼠标移上去时转为最亮。
有任何问题或者写得不清楚的地方,欢迎大家指正。同时也感谢你阅读这篇文章。
更多文章,可以来 http://wpf.5d6d.com 阅读,这里是一个专门的学习WPF技术的论坛!!
[解决办法]
学习了