通通玩blend美工(5)——旋转木马,交互性设计
这一篇偏向于逻辑的比较多,放在这个系列里会不会欠妥呢?在中国交互性设计也是美工的份内职责哦~
所以没有blend基础的人也可以看懂这篇文章,不过要用到初中的几何知识哦~亲
相信很多人都在手机或者网页上或者KTV的点歌系统里看到过旋转木马的目录导航,这个是如何做的呢??
最终效果如下:(貌似有点太大了显示不下,附加个阅览地址:
http://space.silverlightchina.net/ltt147/TTcarousel/Default.html)
(特别鸣谢烤地瓜的答疑,和地瓜村众人的热心帮助)
1.总体思路
分析上面效果:一排方块在转圈,点击的块跑到最近的位置
圈:其实就是一个椭圆,只不过人的近大远小的逻辑思维,大脑根据常识把它装换成了一个空间。
最近的位置:其实就是椭圆的最下面,块变得最大,所以感觉最近。
2.设计过程
首先我们来实现让这堆块围绕成一个椭圆。
step.1 椭圆是这样来产生滴~!↓
我以我微薄的几何知识用blend画出了上图,右上角看到我们久违的椭圆公式。第一个公式当把y单独提到等号一边时发现是要开根号的这样,就如图所看到的,一个x对应着两个y值还得去判断正负号显得麻烦了,就用第二个公式吧。其中a为x半轴,b为y半轴,d为角度。只需要一个角度d就可以确定出这个椭圆中的所有点了。
首先写出变换块位置的方法:
private void SetPosition(Grid item, double degree)
{
TransformGroup myTG = item.RenderTransform as TransformGroup;
TranslateTransform myTT = myTG.Children[] as TranslateTransform;//位置变换
myTT.X = a * Math.Cos(degree);//计算x坐标
myTT.Y = b * Math.Sin(degree);//计算y坐标
item.Tag = degree;
ScaleTransform myST = myTG.Children[1] as ScaleTransform;//大小变换
myST.ScaleX = myST.ScaleY = (1 - scale) / b * myTT.Y + scale;
Canvas.SetZIndex(item, (int)(myTT.Y + 2 * b));//层次变换为Y轴的位置
}
step.2 跟随鼠转标起来吧
这样传入需要变换的块和事先计算的该块的位置所在就角度就可以确定该块的位置、大小、层次了。单mousemove的时候,只要给每一个块都重新定位,把鼠标的移动距离装换为块组需要旋转的角度。
private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)//鼠标移动时转动
{
if (isPress)//如果当前为按住鼠标的状态
{
foreach (Grid item in LayoutRoot.Children)//遍历所有的Grid
{
SetPosition(item, (double)item.Tag + (startPoint.X - e.GetPosition(this).X) * 0.005);//变换位置
}
startPoint.X = e.GetPosition(this).X;//把但前位置赋给开始位置
}
}
我把每个Grid的Tag用来存储自己当前所在的角度。
step.3 点击就转到前面来啊,亲~
接下来制作点击块转动的动画,即点击块后更具该块所在的位置,计算出旋转到90'时需要旋转的角度,然后所有块都转这个角度(为什么是90°呢?应该是270°啊~因为wpf中的位移动画,Y轴移动向下是为正,向上为负,这样就刚好和我们课堂上通用的坐标系刚好上下翻转了)
void newGrid_MouseUp(object sender, MouseButtonEventArgs e)//单击其中一块转正
{
double nowAngle = (double)((sender as Grid).Tag);//根据当前的块的角度
double needAngle = Math.PI / - nowAngle % (Math.PI * );//换算出把改块转正整体需要转动的角度
foreach (Grid item in LayoutRoot.Children)//为每一个块都添加动画
{
degree = (double)item.Tag;//获取各个块的角度
TransformGroup myTG = item.RenderTransform as TransformGroup;
TranslateTransform myTT = myTG.Children[] as TranslateTransform;//位置变换
Storyboard sb = new Storyboard();
sb.Duration = new Duration(TimeSpan.FromMilliseconds(Duration));
DoubleAnimation xAnimation = new DoubleAnimation();
xAnimation.To = a * Math.Cos(degree + needAngle);//计算x坐标
xAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(Duration));
sb.Children.Add(xAnimation);
Storyboard.SetTarget(xAnimation, myTT);
Storyboard.SetTargetProperty(xAnimation, new PropertyPath("X"));
DoubleAnimation yAnimation = new DoubleAnimation();
yAnimation.To = b * Math.Sin(degree + needAngle);//计算x坐标
yAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(Duration));
sb.Children.Add(yAnimation);
Storyboard.SetTarget(yAnimation, myTT);
Storyboard.SetTargetProperty(yAnimation, new PropertyPath("Y"));
ScaleTransform myST = myTG.Children[] as ScaleTransform;//大小变换
DoubleAnimation xScaleAnimation = new DoubleAnimation();
DoubleAnimation yScaleAnimation = new DoubleAnimation();
xScaleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(Duration));
yScaleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(Duration));
if (LayoutRoot.Children.IndexOf(item) == )//只添加一次动画完成后遍历控件改变位置
{
yScaleAnimation.Completed += new EventHandler((s, events) =>//动画结束后把整体的位置调整为动画结束时的位置
{
foreach (Grid item1 in LayoutRoot.Children)
{
SetPosition(item1, (double)item1.Tag);
}
});
}
yScaleAnimation.To = xScaleAnimation.To = ( - scale) / b * yAnimation.To + scale;
sb.Children.Add(xScaleAnimation);
Storyboard.SetTarget(xScaleAnimation, myST);
Storyboard.SetTargetProperty(xScaleAnimation, new PropertyPath("ScaleX"));
sb.Children.Add(yScaleAnimation);
Storyboard.SetTarget(yScaleAnimation, myST);
Storyboard.SetTargetProperty(yScaleAnimation, new PropertyPath("ScaleY"));
sb.Begin();//开始动画
item.Tag = degree + needAngle;//记录最后的角度
}
}
step.4 最靠近下面的要自动对正哦~
OK,接下来还差最有一点就是自动对正了,即当拖动时把最接近最近位置的块自定定位到最近。
原理就是遍历所有块的但前位置,角度越接近90°的就模拟一下它的单击
private void LayoutRoot_MouseUp(object sender, MouseButtonEventArgs e)//当鼠标弹起时判断最近的块,自动转正
{
double minNear = ;
Grid nearGrid = null;
foreach (Grid item in LayoutRoot.Children)//找出最近的Grid
{
double near = Math.Abs(Math.PI / - (double)item.Tag % (Math.PI * ));
if (near < minNear)
{
minNear = near;
nearGrid = item;
}
}
newGrid_MouseUp(nearGrid, null);//模拟最近的块被点了一次
isPress = false;
}
做完收工。
下面是我修改左上角的参数实现的几个比较好看的效果
效率也是很不错的,上面的100个块在我i7的电脑上一点都不卡哦。
大家如果调出什么好看的效果可以贴到回复里,交流下。
我把核心代码都讲了遍,如果还是有不懂的,可以给我留言。当然了这个silverlight版只是作为演示用得第一版,有很多细节方面我没处理。至于源码,因为我做的这个原版是WPF程序作为商用,所以经过多番考虑我还是不公布源码了。当然了我是不会告诉你可以反编译.xap来获取源码的。
通通玩blend美工(5)——旋转木马,交互性设计的更多相关文章
- 通通玩blend美工(6)上——仿iPhone滚动选择器的ListBox(UI设计)
原文:通通玩blend美工(6)上--仿iPhone滚动选择器的ListBox(UI设计) 好久没更新博客了,由于项目比较紧,期间收到不少园友的短消息,感谢大家对我的支持~~. 相信各位都在自己的神机 ...
- 通通玩blend美工(6)下——仿iPhone滚动选择器的ListBox(交互逻辑)
原文:通通玩blend美工(6)下--仿iPhone滚动选择器的ListBox(交互逻辑) 上一篇我们已经把界面画出来了,这篇我们就来制作交互的逻辑吧.上一篇的电梯: http://www.cnblo ...
- 通通玩blend美工(2)——时钟
原文:通通玩blend美工(2)--时钟 谢谢大家对我上一篇Blend的支持:通通玩blend美工(1)——荧光Button 再接再厉再来一篇~~! 这篇是建立在已经看得懂上一篇为基础来写的,有些细节 ...
- 通通玩blend美工(7)——简约而不简单的块
原文:通通玩blend美工(7)--简约而不简单的块 最近在研发一个WPF快速开发框架,满脑子都是各种逻辑各种模式,写一篇比较休闲娱乐的博客,宣泄下我对美工的热爱. 我一直以来有意无意在手机应用或者各 ...
- 通通玩blend美工(3)——可爱的云
原文:通通玩blend美工(3)--可爱的云 好久没有写这个系列的博客了,这里给个电梯吧,照顾新来的同学~~ 通通玩blend美工(1)——荧光Button 通通玩blend美工(2)——时钟 目前我 ...
- 通通玩blend美工(1)——荧光Button
原文:通通玩blend美工(1)--荧光Button 最近老大出差去了,光做项目也有点烦,写点教程消遣消遣(注:此乃初级教程,所以第一个消遣是本人消遣,第二个是指供各位看官消遣...) 看着各位大虾出 ...
- 通通玩blend美工(8)——动态绘制路径动画,画出个萌妹子~
原文:通通玩blend美工(8)--动态绘制路径动画,画出个萌妹子~ 2年前我在玩Flex的时候就一直有一个疑问,就是如何来实现一个蚊香慢慢烧完的Loading动画呢? 刚经历了某甲方高强度一个月的洗 ...
- 没有美工一样可以获取设计各种各样的UI图
没有美工一样可以获取设计各种各样的UI图 http://www.iconfont.cn
- 通通WPF随笔(1)——基于lucene.NET让ComboBox拥有强大的下拉联想功能
原文:通通WPF随笔(1)--基于lucene.NET让ComboBox拥有强大的下拉联想功能 我一直很疑惑百度.谷哥搜索框的下拉联想功能是怎么实现的?是不断地查询数据库吗?其实到现在我也不知道,他们 ...
随机推荐
- js进阶正则表达式13RegExp对象方法(RegExp对象的方法:compile,test,exec)(子表达式 var reg1=/([a-z]+)\d/)
js进阶正则表达式13RegExp对象方法(RegExp对象的方法:compile,test,exec)(子表达式 var reg1=/([a-z]+)\d/) 一.总结 1.RegExp对象有三个方 ...
- 【u020】Couple number
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 任何一个整数N都能表示成另外两个整数a和b的平方差吗?如果能,那么这个数N就叫做Couple numb ...
- python 设计模式之 单例模式
单例模式是做为"全局变量"的替代品出现的.所以它具有全局变量的特点:全局可见.贯穿应用程序的整个生命期,保证在程序执行中,某个类仅仅存在一个实例,所以通常不希望类中的构造函数被调用 ...
- ArcEngine中最短路径的实现
原文 ArcEngine中最短路径的实现 最短路径分析属于ArcGIS的网络分析范畴.而ArcGIS的网络分析分为两类,分别是基于几何网络和网络数据集的网络分析.它们都可以实现最短路径功能.下面先介绍 ...
- 2015年工作中遇到的问题:81-90,标题党-Nginx与真实IP-Mybatis等
81."标题党"与"百度收录"问题. 很久以来,就发现那些"标题党"的收录和排名情况非常好,比如CSDN某篇文章,就随便一写,就排在了第一 ...
- Graphics processing architecture employing a unified shader
FIELD OF THE INVENTION The present invention generally relates to graphics processors and, more part ...
- ACCESS通过一个连接写入的数据,还有一个连接却读取不出来
近期在用c#实现一个数据导入的功能,将一个ACCESS数据库中的数据导入到还有一个ACCESS的数据库中,然后显示出来,可是导入成功了.却显示不出来. 经过研究认为应该是缓存的原因,因为我写入数据和读 ...
- 数码测色计获取UIColor的RGB
1.打开电脑数码测色计 2.鼠标移动到需要的颜色上 3.获取相应RGB值: [UIColor colorWithRed:204.f/255.f green:0.f/255.f blue:212.f/2 ...
- 使用python抓取CSDN关注人的全部公布的文章
# -*- coding: utf-8 -*- """ @author: jiangfuqiang """ import re import ...
- winfrom 操作PPT
///winfrom 操作PPT using System; using System.Collections.Generic; using System.Linq; using System.Tex ...