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

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

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

  

    <ListView ItemsSource="{Binding Photos,Mode=OneTime}" ItemContainerStyle="{StaticResource photoItemContainerStyle}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"></ItemsWrapGrid>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ImageUri,Mode=OneTime}" Stretch="UniformToFill" IsTapEnabled="True" Tapped="Image_Tapped"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

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

  

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

        <Style x:Key="photoItemContainerStyle" TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Duration="0:0:0.5" From="0.5" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPhoto" ></DoubleAnimation>
<DoubleAnimation Duration="0:0:0.5" From="1" To="1.2" Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="scaleGrid" ></DoubleAnimation>
<DoubleAnimation Duration="0:0:0.5" From="1" To="1.2" Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="scaleGrid" ></DoubleAnimation>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups> <Grid.Clip>
<RectangleGeometry Rect="0 0 200 200"/>
</Grid.Clip> <Grid Background="Black">
<ContentPresenter x:Name="contentPhoto" Width="200" Height="200" Opacity="0.5">
<ContentPresenter.RenderTransform>
<ScaleTransform x:Name="scaleGrid" ScaleX="1.0" ScaleY="1.0" CenterX="100" CenterY="100"></ScaleTransform>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</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。

        private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
popup.IsOpen = false; var tappedImage = e.OriginalSource as Image;
var image = new Image { Source = tappedImage.Source };
popup.Child = image;
popup.IsOpen = true; //获取被点击图片相对MainPage的坐标
var position = tappedImage.TransformToVisual(this).TransformPoint(new Point());
//获取MainPage的中心坐标
var xCenter = ActualWidth / - ;
var yCenter = ActualHeight / - ; var storyBoard = new Storyboard();
var extendAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = , To = , EnableDependentAnimation = true };
Storyboard.SetTarget(extendAnimation, image);
Storyboard.SetTargetProperty(extendAnimation, "Width");
Storyboard.SetTargetProperty(extendAnimation, "Height"); var xAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = position.X, To = xCenter, EnableDependentAnimation = true };
Storyboard.SetTarget(xAnimation, popup);
Storyboard.SetTargetProperty(xAnimation, "(UIElement.RenderTransform).(TranslateTransform.X)"); var yAnimation = new DoubleAnimation { Duration = new Duration(TimeSpan.FromSeconds(0.5)), From = position.Y, To = yCenter, EnableDependentAnimation = true };
Storyboard.SetTarget(yAnimation, popup);
Storyboard.SetTargetProperty(yAnimation, "(UIElement.RenderTransform).(TranslateTransform.Y)"); storyBoard.Children.Add(extendAnimation);
storyBoard.Children.Add(xAnimation);
storyBoard.Children.Add(yAnimation); storyBoard.Begin();
}

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

    public sealed partial class MainPage : Page
{
public List<PhotoModel> Photos { get; set; } private Popup popup = new Popup(); public MainPage()
{
this.InitializeComponent();
Photos = CreatePhotos();
this.DataContext = this;
popup.RenderTransform = new TranslateTransform();
}

  总体就这么些了,大约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. CI框架,源代码一次性判断获取post(get)数据是否有某个字段值为空方法

    一.以下是CI框架 1.把所有的要接收的字段放在数组中 例: 我要接收:id,name,age,mobile 等字段 $req = array('id','name','age','mobile'); ...

  2. Apache与Nginx区别

    1.nginx相对于apache的优点: 轻量级,同样起web 服务,比apache占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx ...

  3. 5.Powershell变量

    在指令执行过程中,会有一些数据产生,这些数据被用于以后的语句,需要一个存储单元暂时的存放这些数据,这个时候定义一个变量来存储数据.例如$string = “Hello Powershell!” Pow ...

  4. 从Undo,Redo谈命令模式

    一般的应用软件中,通常会提供Redo和Undo的操作,比如Paint.NET中的动作面板,Word中的撤销重做,一般我们按Ctrl-Z即可回退到上次操作. 要实现上面的这一功能,最直观的想法就是,我们 ...

  5. Functional Programming without Lambda - Part 1 Functional Composition

    Functions in Java Prior to the introduction of Lambda Expressions feature in version 8, Java had lon ...

  6. Leetcode 刷题计划

    Two Sum    21.4%    Medium Given an array of integers, return indices of the two numbers such that t ...

  7. 跟我一起数据挖掘(22)——spark入门

    Spark简介 Spark是UC Berkeley AMP lab所开源的类Hadoop MapReduce的通用的并行,Spark,拥有Hadoop MapReduce所具有的优点:但不同于MapR ...

  8. springboot之filter/listener/servlet

    简介 SpringBoot可以简化开发流程,但是在其中如何使用传统的J2EE servlet/listener/filter呢 @Bean配置 在Configuration类中加入filter和ser ...

  9. EF for Oracle,dotConnect for Oracle,ODP.NET

    dotConnect for Oracle dotConnect for Oracle是一款为Microsoft .NET Framework提供直接Oracle数据库连接的数据发生器控件.它完全基于 ...

  10. 预处理(防止sql注入的一种方式)

    <!--- 预处理(预编译) ---><?php/* 防止 sql 注入的两种方式: 1. 人为提高代码的逻辑性,使其变得更严谨,滴水不漏. 比如说 增加判断条件,增加输入过滤等,但 ...