微博上有同学问我MyerSplash是如何实现那个很炫的图片点亮,然后移动到屏幕中央的效果。惭愧啊,我又不是作者哪里会知道。硬着头皮去GitHub拜读了高手的代码,自愧弗如,比我不知道高到哪里去了……这时我就面临一个艰难的抉择,要么就写个几十篇来分析一下MyerSplash(万一分析错了好丢人……),要么就说看不懂(貌似也很丢人……)。

  幸亏我临机一动,决定山寨一个极简版,做一点微小的工作,顺便写一篇博客蹭点热度,给某软,给UWP续一秒……

  首先要明确我们希望以少量的代码来模拟MyerSplash的部分效果,较少的代码分析起来更为易懂,所以各位同学就不要抱怨说这个是五毛钱特效……

  

  1. <ListView ItemsSource="{Binding Photos,Mode=OneTime}" ItemContainerStyle="{StaticResource photoItemContainerStyle}">
  2. <ListView.ItemsPanel>
  3. <ItemsPanelTemplate>
  4. <ItemsWrapGrid Orientation="Horizontal"></ItemsWrapGrid>
  5. </ItemsPanelTemplate>
  6. </ListView.ItemsPanel>
  7. <ListView.ItemTemplate>
  8. <DataTemplate>
  9. <Image Source="{Binding ImageUri,Mode=OneTime}" Stretch="UniformToFill" IsTapEnabled="True" Tapped="Image_Tapped"></Image>
  10. </DataTemplate>
  11. </ListView.ItemTemplate>
  12. </ListView>

  上面的XAML绘制了一个根据元素数量自动换行的列表,列表中的Item元素就是单纯的Image,同时Item元素响应一个Tapped事件(这个我们后面说)。

  

  可以看到鼠标移动时,会有一个动画,0.5秒的渐变点亮同时图片放大的效果(生成的这个gif图比较渣,实际效果请运行代码)。这是通过自定义ItemContainerStyle并在其中添加VisualStateManager来实现的。

  1. <Style x:Key="photoItemContainerStyle" TargetType="ListViewItem">
  2. <Setter Property="Template">
  3. <Setter.Value>
  4. <ControlTemplate>
  5. <Grid>
  6. <VisualStateManager.VisualStateGroups>
  7. <VisualStateGroup x:Name="CommonStates">
  8. <VisualState x:Name="Normal" />
  9. <VisualState x:Name="PointerOver">
  10. <Storyboard>
  11. <DoubleAnimation Duration="0:0:0.5" From="0.5" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPhoto" ></DoubleAnimation>
  12. <DoubleAnimation Duration="0:0:0.5" From="1" To="1.2" Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="scaleGrid" ></DoubleAnimation>
  13. <DoubleAnimation Duration="0:0:0.5" From="1" To="1.2" Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="scaleGrid" ></DoubleAnimation>
  14. </Storyboard>
  15. </VisualState>
  16. </VisualStateGroup>
  17. </VisualStateManager.VisualStateGroups>
  18.  
  19. <Grid.Clip>
  20. <RectangleGeometry Rect="0 0 200 200"/>
  21. </Grid.Clip>
  22.  
  23. <Grid Background="Black">
  24. <ContentPresenter x:Name="contentPhoto" Width="200" Height="200" Opacity="0.5">
  25. <ContentPresenter.RenderTransform>
  26. <ScaleTransform x:Name="scaleGrid" ScaleX="1.0" ScaleY="1.0" CenterX="100" CenterY="100"></ScaleTransform>
  27. </ContentPresenter.RenderTransform>
  28. </ContentPresenter>
  29. </Grid>
  30. </Grid>
  31. </ControlTemplate>
  32. </Setter.Value>
  33. </Setter>

  在 <VisualState x:Name="PointerOver">这个状态我们通过Storyboard播放了三个Animation来改变图片的透明度,以及长宽。透明度从0.5变化至1时,图片不再透明,背景黑色Grid不再可见,模拟高亮效果。同时通过Clip将放大后图片的外缘裁剪仍保持原始大小。

  貌似已经做的差不多了……至少你已经学会如何山寨照片墙了。接下来我们要做点不一样的,换一种方式来使用Storyboard和Animation,点击图片放大并移动到屏幕中央的功能,我打算通过C#代码实现(话说这部分有点坑,写得时候搞死我了……)

  浮动显示的图片我们采用Popup来显示,通过给Popup添加Child,并通过storyboard和animation来改变Width,Height属性控制图片大小的变化。图片的位移则是将Popup的RenderTransform属性设置为TranslateTransform,然后改变X轴和Y轴坐标来实现。

  这里需要注意Animation对象的EnableDependentAnimation属性,这个坑爹的属性是 Windows Runtime 8.1新增的,如果你发现自定义的Animation不能播放,又找不到任何错误,那就需要把这个属性值置为true。

  1. private void Image_Tapped(object sender, TappedRoutedEventArgs e)
  2. {
  3. popup.IsOpen = false;
  4.  
  5. var tappedImage = e.OriginalSource as Image;
  6. var image = new Image { Source = tappedImage.Source };
  7. popup.Child = image;
  8. popup.IsOpen = true;
  9.  
  10. //获取被点击图片相对MainPage的坐标
  11. var position = tappedImage.TransformToVisual(this).TransformPoint(new Point());
  12. //获取MainPage的中心坐标
  13. var xCenter = ActualWidth / - ;
  14. var yCenter = ActualHeight / - ;
  15.  
  16. var storyBoard = new Storyboard();
  17. var extendAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = , To = , EnableDependentAnimation = true };
  18. Storyboard.SetTarget(extendAnimation, image);
  19. Storyboard.SetTargetProperty(extendAnimation, "Width");
  20. Storyboard.SetTargetProperty(extendAnimation, "Height");
  21.  
  22. var xAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = position.X, To = xCenter, EnableDependentAnimation = true };
  23. Storyboard.SetTarget(xAnimation, popup);
  24. Storyboard.SetTargetProperty(xAnimation, "(UIElement.RenderTransform).(TranslateTransform.X)");
  25.  
  26. var yAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = position.Y, To = yCenter, EnableDependentAnimation = true };
  27. Storyboard.SetTarget(yAnimation, popup);
  28. Storyboard.SetTargetProperty(yAnimation, "(UIElement.RenderTransform).(TranslateTransform.Y)");
  29.  
  30. storyBoard.Children.Add(extendAnimation);
  31. storyBoard.Children.Add(xAnimation);
  32. storyBoard.Children.Add(yAnimation);
  33.  
  34. storyBoard.Begin();
  35. }

  补充下Popup的定义,记得要设置popup.RenderTransform = TranslateTransform(),默认可是null

  1. public sealed partial class MainPage : Page
  2. {
  3. public List<PhotoModel> Photos { get; set; }
  4.  
  5. private Popup popup = new Popup();
  6.  
  7. public MainPage()
  8. {
  9. this.InitializeComponent();
  10. Photos = CreatePhotos();
  11. this.DataContext = this;
  12. popup.RenderTransform = new TranslateTransform();
  13. }

  总体就这么些了,大约100行左右的代码,直接拿去卖钱肯定是不行的。作为Demo演示给吃瓜群众,或者忽悠BOSS还是可以的。如果需要用到产品中,去GayHub下载代码自己改吧改吧,调调UI。

  有问题新浪微博@楼上那个蜀黍,免费咨询,当然质量也是免费的程度……

  GitHub:

  https://github.com/manupstairs/UWPSamples/tree/master/UWPSamples/StoryboardSample

UWP开发入门(二十二)——Storyboard和Animation的更多相关文章

  1. UWP开发入门(十二)——神器Live Visual Tree

    很久以前,我们就有Snoop这样的工具实时修改.查看正在运行的WPF程序,那时候调个样式,修改个模板,相当滋润.随着历史的车轮陷进WP的泥潭中,无论WP7的Silverlight还是WP8.1的run ...

  2. UWP开发入门(十)——通过继承来扩展ListView

    本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念.而是通过继承的方法来扩展一个现有的类,在继承的 ...

  3. UWP开发入门(十六)——常见的内存泄漏的原因

    本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...

  4. UWP开发入门(十九)——10分钟学会在VS2015中使用Git

    写程序必然需要版本控制,哪怕是个人项目也是必须的.我们在开发UWP APP的时候,VS2015默认提供了对微软TFS和Git的支持.考虑到现在Git很火,作为微软系的程序员也不得不学一点防身,以免被开 ...

  5. UWP开发入门(十八)——使用ContentControl减少页面元素数量

    我们今天学习一下ContentControl,主要介绍如何使用ContentControl搭配DataTemplate来进行界面的复用,以及通过ContentTemplateSelector进一步减少 ...

  6. UWP开发入门(十五)——在FlipView中通过手势操作图片

    本篇的最终目的,是模拟系统的照片APP可以左右滑动,缩放图片的操作.在实现的过程中,我们会逐步分析UWP编写UI的一些思路和技巧. 首先我们先实现一个横向的可以浏览图片的功能,也是大部分APP中的实现 ...

  7. UWP开发入门(十四)—— UserControl中Adaptive UI的小技巧

    本篇我们通过绘制一个非常简单的UserControl控件,来分享一下对Adaptive UI的理解及一些图形绘制的技巧. 现在流行的APP都少不了精致的用户头像,首先假设我们需要绘制如下的图形作为默认 ...

  8. UWP入门(十二)--数据绑定用法

    原文:UWP入门(十二)--数据绑定用法 主要几个元素: Template DataTemplate ItemSource 数据绑定是一个数据提取的方法,能使数据和UI上的控件紧密相连,下面的Demo ...

  9. Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十二】

    <Web 前端开发精华文章推荐>2014年第一期(总第二十二期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML ...

  10. Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明

    紧接上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>,这里专讲OAuth2.0. 理解OAuth2.0 首先我们通过一张图片来了解一下OAu ...

随机推荐

  1. webserver几个例子

    刚刚学习了web服务,实现了发布和调用电话号码归属地查询,下面我简单的说一下 第一个方法利用网页实现号码查询: 首先进入http://www.webxml.com.cn/网站 然后点这个 输入手机号码 ...

  2. ASP.NET Core 数据保护(Data Protection)【中】

    前言 上篇主要是对 ASP.NET Core 的 Data Protection 做了一个简单的介绍,本篇主要是介绍一下API及使用方法. API 接口 ASP.NET Core Data Prote ...

  3. 浅析 Linux 初始化 init 系统

    近年来,Linux 系统的 init 进程经历了两次重大的演进,传统的 sysvinit 已经逐渐淡出历史舞台,新的 UpStart 和 systemd 各有特点,越来越多的 Linux 发行版采纳了 ...

  4. Python黑帽编程 3.2 ARP监控

    Python黑帽编程 3.2 ARP监控 在第3.1节<ARP欺骗>中,我们学习了ARP的基本原理,使用Python实现了我们自己的ARP欺骗工具.在上一节的基础上,我们来实现一个ARP监 ...

  5. Javascript分号,加还是不加?

    关于这个问题,网上已经有很多人讨论过了,我先说说自己对这个问题的回答:加!(但非必须) 有些人写代码,懒得加分号,除非是迫不得已才勉强放一个分号上去.如果你可以保证你写的代码不出现任何 bug,那当然 ...

  6. SQLSERVER语句 in和exists哪个效率高本人测试证明

    SQLSERVR语句 in和exists哪个效率高本人测试证明 最近很多人讨论in和exists哪个效率高,今天就自己测试一下 我使用的是客户的数据库GPOSDB(已经有数据) 环境:SQLSERVE ...

  7. 人生苦短,我用python——当我在玩python的时候我玩些什么

    文章背景 家里的第一台电脑是在2006年夏天买的,10年上大学之后基本上就没人用,过没两年就当二手卖给一个熟人. 弟弟小我10岁,今年刚上初一.他在我毕业前半年就整天用妈妈的手机发短信给我,问我什么时 ...

  8. Hibernate 3.3.2 文档翻译 Day01

    Hibernate 3.3.2 文档翻译 翻译人:微冷的雨 第一次书写:2015年11月29日 本人呕心沥血之作,请细心阅读领悟! Day01-1.1 项目描述 微冷的雨翻译:例如,我们将要建立一个可 ...

  9. FASTJSON

    package com.hanqi.test; import java.util.ArrayList;import java.util.Date;import java.util.List; impo ...

  10. Execute SQL Task 参数和变量的映射

    Execute SQL Task能够执行带参数的SQL查询语句或存储过程(SP),通过SSIS的变量(Variable)对参数赋值.对于不同的Connection Manager,在Task中需要使用 ...