Silverlight 模拟Nano5 界面效果
前一阵无意中发现将iPod Nano5 横置后会出现一个动态的选歌界面(如下图示),感觉不错于是想用Silverlight来实现一下这个效果,欢迎大家拍砖。
本来是放Demo演示,可是这个程序怎么也显示不出来,只好用图片了(感兴趣的话可以下载源代码):
在制作过程中比较繁琐的部分是倒影效果,最开始的做法是将同一张专辑图片使用两次:一个作为专辑封面;一个作为倒影效果。对倒影效果图片进行RenderTransform->ScaleY 反转和OpacityMask->LinearGradientBrush 渐变处理,这样操作后出现一个问题:未选中专辑的封面和倒影之间有间隙(如下图示)。这是由于分别对封面和倒影进行PlaneProjection->RotationY 三维旋转时会使它们按各自的坐标轴进行旋转,不是以一个整体进行旋转而差生了偏差。如果将两个图片组合为一个StackPanel 或Canvas 然后再进行旋转感觉应该可以(但需要不少代码实现,效率可能会降低,感兴趣的朋友可以测试一下),最后偷懒用PS 给图片做了倒影~
下面先来看看XAML,这部分就是为Canvas 增加一些事件:
<Canvas x:Name="LayoutRoot" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown"> </Canvas>
C# 内容请看注释详解:
public partial class MainPage : UserControl { private String[] ALBUMS = { "images/ep1.png", "images/ep2.png", "images/ep3.png", "images/ep4.png", "images/ep5.png", "images/ep6.png", "images/ep7.png", "images/ep8.png", "images/ep9.png" }; //当前位置 private double CURRENT = 0; //目标位置 private double TARGET = 0; //存储图片 private List<Image> IMAGE = new List<Image>(); //计时器 private DispatcherTimer TIMER = new DispatcherTimer(); public MainPage() { InitializeComponent(); //加载图片 addImages(); //对于不同浏览器加载滚轮事件 HtmlPage.Window.AttachEvent("DOMMouseScroll", LayoutRoot_MouseWheel); HtmlPage.Window.AttachEvent("onmousewheel", LayoutRoot_MouseWheel); HtmlPage.Document.AttachEvent("onmousewheel", LayoutRoot_MouseWheel); } private void addImages() { for (int i = 0; i < ALBUMS.Length; i++) { //逐一加载图片 string url = ALBUMS[i]; Image cover = new Image(); cover.Source = new BitmapImage(new Uri(url, UriKind.Relative)); LayoutRoot.Children.Add(cover); //调整图片显示方式 setImage(cover, i); //将图片加入IMAGE,用于实现动态效果 IMAGE.Add(cover); } } private void setImage(Image image, int index) { //遍历图片与当前(CURRENT)位置关系 double offset = index - CURRENT; //对图片进行三维旋转 PlaneProjection planeProjection = new PlaneProjection(); planeProjection.RotationY = Math.Abs(offset) * 65 / (offset != 0 ? offset : 1); image.Projection = planeProjection; double left; double top = 50; double center = Width / 2 - 100; double scale = 1; if (index == CURRENT) { left = center; top = 40; scale = 1.15; } else if (index > CURRENT) { left = center + offset * 50 + 60; } else { left = center + offset * 50 - 40; } //对CURRENT图片进行缩放 ScaleTransform scaleTransform = new ScaleTransform(); scaleTransform.ScaleX = scale; scaleTransform.ScaleY = scale; image.RenderTransform = scaleTransform; //调整遍历图片位置 image.SetValue(Canvas.LeftProperty, left); image.SetValue(Canvas.TopProperty, top); image.SetValue(Canvas.ZIndexProperty, (int)(-Math.Abs(offset)) * 100); } //点击鼠标左键正向移动图片 private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { moveIndex(1); } /* * 如果将下面事件加入Canvas的MouseWheel="LayoutRoot_MouseWheel"(XAML)中, * 页面加载后初始不能获取滚轮事件。 */ //private void LayoutRoot_MouseWheel(object sender, MouseWheelEventArgs e) //{ // double mouseDelta = 0; // mouseDelta = Math.Sign(e.Delta); // moveIndex((mouseDelta > 0) ? 1 : -1); //} //通过HtmlPage加载鼠标滚动事件,详情可参考资料<4> private void LayoutRoot_MouseWheel(object sender, HtmlEventArgs args) { double mouseDelta = 0; ScriptObject e = args.EventObject; // Mozilla and Safari if (e.GetProperty("detail") != null) { mouseDelta = ((double)e.GetProperty("detail")); } // IE and Opera else if (e.GetProperty("wheelDelta") != null) mouseDelta = ((double)e.GetProperty("wheelDelta")); mouseDelta = Math.Sign(mouseDelta); moveIndex((mouseDelta > 0) ? 1 : -1); } private void moveIndex(int value) { //获取目标图片位置,并确保其在图片数量范围内 TARGET += value; TARGET = Math.Max(0, TARGET); TARGET = Math.Min(IMAGE.Count - 1, TARGET); } //计时器Tick,移动到目标图片 private void timerTick(object sender, EventArgs e) { for (int i = 0; i < IMAGE.Count; i++) { Image image = IMAGE[i]; setImage(image, i); } CURRENT = TARGET; } //启动计时器 public void startShow() { TIMER = new DispatcherTimer(); TIMER.Interval = new TimeSpan(0, 0, 0, 0, 10); TIMER.Tick += new EventHandler(timerTick); TIMER.Start(); } }
至此,Nano5 的界面效果已完成,借此作品献给已世的 * MJ * 。
相关参考资料:
1. LinearGradientBrush类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.lineargradientbrush.aspx
2. 三维效果(透视转换)
http://msdn.microsoft.com/zh-cn/library/dd470131(VS.95).aspx
3. DispatcherTimer 类
http://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatchertimer(VS.95).aspx
4. How to Capture the Mouse Wheel Event
http://blogs.silverlight.net/blogs/msnow/archive/2008/07/29/tip-of-the-day-23-how-to-capture-the-mouse-wheel-event.aspx
源代码下载:
出处:{GnieTech} (http://www.cnblogs.com/gnielee/)
版权声明:本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任。