http://yichuanshen.de/blog/2010/11/13/flipping-elements-with-wpf/

Have you already seen ForgottenTime’s new flip animation eye candy? If not, it’s about time! It took me several days to figure out how to do it…

My first thought was to find out how to do a 4-point-tranformation of a given image. (See figure on the left.) It’s no problem to create an “screenshot” of a UI element and I could easily calculate the four vertices of the transformed image (with given angle and a little bit trigonometry) and transform the original screenshot via the function to achieve a 3D effect. Unfortunately, there’s no (easy and fast) way to do that in C# and Windows Presentation Framework, so I had to think of something else.

After my research on the Internet I came across some official demo WPF applications, also using advanced UI techniques such as flipping. So I dug into the code to find out how they did it. As it turned out, they were using 3D graphics.

WELCOME TO THE 3RD DIMENSION

Strictly speaking a computer screen cannot display real 3D graphics of course, only projections of a 3D space onto a plane… the screen. It’s also called a “viewport”, a 2D window, that allows the user to gaze into the imaginary 3D space behind. Just like we have eyes, a viewport needs a “camera” (to be really precise, a PerspectiveCamera).

Let’s assume the image we want to flip is a square with the dimensions 129×129.

<!-- XAML code -->
<Viewport3D x:Name="viewport3D" Width="129" Height="129">
<Viewport3D.Resources>
</Viewport3D.Resources>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="cam3D"
FieldOfView="45"
LookDirection="0,0,-1 "
UpDirection="0,1,0" />
</Viewport3D.Camera>
</Viewport3D>

After the window is loaded, we create a two-dimensional object, a square, which represents our image in 3D space and calculate where our camera should be. If all that is done, we can literally rotate the object around the y-axis and thus flip the image around.

THE TWO-DIMENSIONAL OBJECT

Every object in our 3D space is made of triangles. The triangle surface of such an object is called a mesh. It’s relatively easy to build a square out of two triangles as the sketch below shows.

We center the image around the origin, so that the camera can be easily positioned on the z-axis. To create such a simple object (notice this is two-dimensional!) you have to write tons of code:

// C# code
GeometryModel3D model3D; private void BuildModel() {
// Customize the brushes
// Can be any brush (ImageBrush, DrawingBrush, VisualBrush, ...)
ImageBrush front = new ImageBrush(this.frontImageSource);
ImageBrush back = new ImageBrush(this.backImageSource);
back.Transform = new ScaleTransform(-1, 1, .5, 0); // Flip back image // Create mesh
MeshGeometry3D mesh = new MeshGeometry3D();
double radius = 129 / 2.0; // 64.5
mesh.Positions.Add(new Point3D(-radius, -radius, 0));
mesh.Positions.Add(new Point3D(radius, -radius, 0));
mesh.Positions.Add(new Point3D(radius, radius, 0));
mesh.Positions.Add(new Point3D(-radius, radius, 0));
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(2);
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(2);
mesh.TriangleIndices.Add(3);
mesh.TextureCoordinates.Add(new Point(0, 1));
mesh.TextureCoordinates.Add(new Point(1, 1));
mesh.TextureCoordinates.Add(new Point(1, 0));
mesh.TextureCoordinates.Add(new Point(0, 0)); // Add texture
DiffuseMaterial frontMat = new DiffuseMaterial(front);
DiffuseMaterial backMat = new DiffuseMaterial(back);
frontMat.AmbientColor = backMat.AmbientColor = Colors.White; model3D = new GeometryModel3D();
model3D.Geometry = mesh;
model3D.Material = frontMat;
model3D.BackMaterial = backMat; Model3DGroup group = new Model3DGroup();
group.Children.Add(model3D);
group.Children.Add(new AmbientLight(Colors.White)); ModelVisual3D visual = new ModelVisual3D();
visual.Content = group;
viewport3D.Children.Add(visual);
}

THE CAMERA POSITION

The camera has to be some distance away from the square, so that everything is within the camera’s field of view. Especially when the image is rotated by 90˚ around the y-axis, where it’s nearest to the camera. So how do we calculate the distance?

The sketch above shows the image which has already been rotated by 90˚. Let’s first look at the left side of the sketch. As we can see the camera is positioned . We’re going to calculate x using tangent.

Now if we put the camera at  it’s garanteed that everything is visible in the viewport. But as we can see in the sketch above, there’s space below and above (as well as left and right) the original unrotated image (space marked with variable s) which will make the image appear smaller in the viewport. We have to enlarge the viewport, so that the image will appear normal-sized again. We can calculate s as follows:

Now we have made all calculations, we can (finally) transform everything into code:

// C# code
private void PositionCamera() {
double radius = 129 / 2.0; // 64.5 // Calculate 3D cam position for flip animation
double x = radius / Math.Tan(degToRad(45 / 2.0));
cam3D.Position = new Point3D(0, 0, x + radius); // Add border for flip animation
double s = radius * Math.Tan(degToRad(45 / 2.0));
viewport3D.Height = viewport3D.Width = 2 * radius + 2 * s;
} private void Window_Loaded(object sender, RoutedEventArgs e) {
BuildModel();
PositionCamera();
} private double degToRad(double deg) {
return deg / 180 * Math.PI;
}

The degToRad function is needed, because C#’s Trigonometry only takes radian angles.

THE ANIMATION

Now that we have painstakingly set up our beautiful 3D scene, we can finally animate it!

// C# code
public void Flip() {
// Rotate
AxisAngleRotation3D rotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
model3D.Transform = new RotateTransform3D(rotation, new Point3D(0, 0, 0)); DoubleAnimation flipAnimation = new DoubleAnimation(0, 180, new Duration(TimeSpan.FromMilliseconds(1000)));
/* To flip back just swap 0 and 180 ;) */ // Do magic!
rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, flipAnimation);
}

Try it out! What a glorious effect! Once you saw it, you can’t seem to stop starting the animation over and over again.

Flipping elements with WPF的更多相关文章

  1. WPF 3D 知识点大全以及实例

    引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当 ...

  2. 30个惊人的插件来扩展 Twitter Bootstrap

    Bootstrap Maxlength It is a lightweight plugin that allows detecting the HTML maxlength property of ...

  3. Github资源汇集

    Github资源汇集 突然发现申请博客园已经两年有余,没有发表过一篇文章,十分惭愧.言归正传,先分享一下两年来收集的部分编程资源,大部分为Github上的项目.虽然网上这样的分享已不在少数,但不如我理 ...

  4. 3D开发基础知识和简单示例

    引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当 ...

  5. 关于WPF你应该知道的2000件事

    原文 关于WPF你应该知道的2000件事 以下列出了迄今为止为WPF博客所知的2,000件事所创建的所有帖子. 帖子总数= 1,201 动画 #7 - 基于属性的动画 #686 - 使用动画制作图像脉 ...

  6. 2000条你应知的WPF小姿势 基础篇<69-73 WPF Freeze机制和Template>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...

  7. 2000条你应知的WPF小姿势 基础篇<15-21>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师,对C#和WPF有着极深的热情.最为出色的是他维护了两个博客:2,000Things You Should Know ...

  8. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇二:基于OneNote难点突破和批量识别

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  9. WPF下的Richtextbox中实现表格合并,添加删除行列等功能

    .Net中已有现在的方法实现这些功能,不过可能是由于未完善,未把方法公开出来.只能用反射的方法去调用它. 详细信息可以查看.Net Framework 的源代码 http://referencesou ...

随机推荐

  1. Python 中 sqlite3的使用

    Python 中 sqlite3的使用 一.sqlite安装 下载地址 http://www.sqlite.org 1.数据库生成 sqlite3.exe testdb 2.创建表格,插入数据 3.在 ...

  2. (译)cocos2d-x跨android&ios平台开发入门教程

    免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作 ...

  3. FIM相关报错汇总

    1.错误1:FIM在修改MA名字的时候报错: The management agent cannot be deleted or renamed because the working directo ...

  4. poj 1021矩阵平移装换后是否为同一个矩阵

    2D-Nim Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3081   Accepted: 1398 Descriptio ...

  5. 获取root权限

    1.用root建立一个普通用户mary,并切换到mary. < 2.我们首先测试一下当前用户的权限 3.进入到/tmp,新建目录abc. 4.执行下列相关命令.并保证最后一行后面的两块红色部分为 ...

  6. line-height,vertical-align及图片居中对齐问题根源解析

    关于图片居中对齐的问题,进入前端行业虽然有一段时间了,以为自己懂了,可是实际上还是一知半解,找了一些博客来看了一下,但是感觉讲的有点碎,看完还是一知半解. 查阅了一下<css权威指南>,结 ...

  7. Makeflow 4.0 发布,工作流引擎

    Makeflow 4.0 发布了,主要改进包括: 1. 支持分层次的 workers,带 master-foremen-workers 范式. 2. 一个 worker 可同时处理超过 1 个的任务3 ...

  8. 仿SiteMap实现Asp.net 网站的菜单和权限管理

    在Asp.net中,SiteMap用于站点导航,可以与Menu等控件一起使用实现网站的菜单和权限管理.但是SiteMap提供的方法都是只读的,无法再运行时修改(菜单)导航文件,需要手动修改配置web. ...

  9. JqueryEasyUI浅谈---视频教程公布

    http://pan.baidu.com/s/1pJqGXez 前两天我在博客园发了一个关于JqueryEasyUI浅谈本地化应用的博客,我简单的介绍了JqueryEasyUI的应用,今天我录制了了一 ...

  10. SQL 注入

    我们的团队项目中有课程名称输入框,其中的内容会拼接到类sql查询语句中. 所以可能会产生类sql注入的问题,我们团队采用了利用正则表达式判断输入内容的形式来规避这类注入. 下面简单介绍一下sql注入 ...