原文:通通玩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)——旋转木马,交互性设计的更多相关文章

  1. 通通玩blend美工(6)上——仿iPhone滚动选择器的ListBox(UI设计)

    原文:通通玩blend美工(6)上--仿iPhone滚动选择器的ListBox(UI设计) 好久没更新博客了,由于项目比较紧,期间收到不少园友的短消息,感谢大家对我的支持~~. 相信各位都在自己的神机 ...

  2. 通通玩blend美工(6)下——仿iPhone滚动选择器的ListBox(交互逻辑)

    原文:通通玩blend美工(6)下--仿iPhone滚动选择器的ListBox(交互逻辑) 上一篇我们已经把界面画出来了,这篇我们就来制作交互的逻辑吧.上一篇的电梯: http://www.cnblo ...

  3. 通通玩blend美工(2)——时钟

    原文:通通玩blend美工(2)--时钟 谢谢大家对我上一篇Blend的支持:通通玩blend美工(1)——荧光Button 再接再厉再来一篇~~! 这篇是建立在已经看得懂上一篇为基础来写的,有些细节 ...

  4. 通通玩blend美工(7)——简约而不简单的块

    原文:通通玩blend美工(7)--简约而不简单的块 最近在研发一个WPF快速开发框架,满脑子都是各种逻辑各种模式,写一篇比较休闲娱乐的博客,宣泄下我对美工的热爱. 我一直以来有意无意在手机应用或者各 ...

  5. 通通玩blend美工(3)——可爱的云

    原文:通通玩blend美工(3)--可爱的云 好久没有写这个系列的博客了,这里给个电梯吧,照顾新来的同学~~ 通通玩blend美工(1)——荧光Button 通通玩blend美工(2)——时钟 目前我 ...

  6. 通通玩blend美工(1)——荧光Button

    原文:通通玩blend美工(1)--荧光Button 最近老大出差去了,光做项目也有点烦,写点教程消遣消遣(注:此乃初级教程,所以第一个消遣是本人消遣,第二个是指供各位看官消遣...) 看着各位大虾出 ...

  7. 通通玩blend美工(8)——动态绘制路径动画,画出个萌妹子~

    原文:通通玩blend美工(8)--动态绘制路径动画,画出个萌妹子~ 2年前我在玩Flex的时候就一直有一个疑问,就是如何来实现一个蚊香慢慢烧完的Loading动画呢? 刚经历了某甲方高强度一个月的洗 ...

  8. 没有美工一样可以获取设计各种各样的UI图

    没有美工一样可以获取设计各种各样的UI图 http://www.iconfont.cn

  9. 通通WPF随笔(1)——基于lucene.NET让ComboBox拥有强大的下拉联想功能

    原文:通通WPF随笔(1)--基于lucene.NET让ComboBox拥有强大的下拉联想功能 我一直很疑惑百度.谷哥搜索框的下拉联想功能是怎么实现的?是不断地查询数据库吗?其实到现在我也不知道,他们 ...

随机推荐

  1. html 页面 黑白

    css代码,写在最顶端 html {filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);-webkit-filter: ...

  2. Ajax的get、post和ajax提交

    JQuery.get(url,[data],[callback],[type]) []里面的参数是可选的,不是必填的. [data]:带发送的key/value数据. [callback]:载入成功时 ...

  3. Net Core 下 Newtonsoft.Json 转换字符串 null 替换成string.Empty

    原文:Net Core 下 Newtonsoft.Json 转换字符串 null 替换成string.Empty public class NullToEmptyStringResolver : De ...

  4. [Angular] @ContentChild and ngAfterContentInit

    @ContentChild normally works with ngAfterContentInit lifecycle. @ContentChild is used for looking in ...

  5. 小强的HTML5移动开发之路(37)——jqMobi快速入门

    在<小强的HTML5移动开发之路(33)-- jqMobi基础>中我们了解了什么是jqMobi,并从官方下载了jqMobi开发包,下载后解压目录如下: 拷贝上面的/css目录./plugi ...

  6. BZOJ1297 迷路 - 矩阵的幂

    传送门 题目大意: 输入n(点的数量),t(时间),和一个n*n的矩阵,第i行第j列表示第i个节点到第j个节点有一条matrix[i][j](0~9)时间的边,若为0则没有边,问从1到n恰好经过t时间 ...

  7. 检索06 - Oracle MySql SqlSever之间的区别和优缺点

    三者之间区别 历史 1 Oracle:中文译作甲骨文,这是一家传奇的公司,有一个传奇的大老板Larry Ellision. Ellision 32岁还一事无成,读了三个大学,没得到一个学位文凭,换了十 ...

  8. 【t006】三角形分形描绘问题

    Time Limit: 1 second Memory Limit: 50 MB [问题描述] 分形是以多种概念和方法相互冲击融合为特征的图形.分形所呈现的无穷玄机和美感引发人们去探索.分形使人们觉悟 ...

  9. 机房收费系统vb.net之打包与部署(一)

    从机房重构到如今,我最大的感受就是万事开头难,万事结尾难!开头难是由于那个思路理不清,对三层已经设计模式的应用不够熟悉,结尾难就是打包部署了!这几天非常头疼,以为完毕了代码就大功告成了,但是没想到啊, ...

  10. DELPHI高性能大容量SOCKET并发(八):断点续传(上传也可以续传)

    断点续传 断点续传主要是用在上传或下载文件,一般做法是开始上传的时候,服务器返回上次已经上传的大小,如果上传完成,则返回-1:下载开始的时候,由客户端上报本地已经下载大小,服务器根据位置信息下发数据, ...