原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)
pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依赖属性也不介绍。),个人认为,依赖属性这个东西,有百分之五十是为了3D而存在。
(自己写的类似于demo的东西)
先上图,无图无真相
这是demo的整个效果图,可以用鼠标移动,触摸屏也可以手指滑动,图片会移动,然后移动结束,会有一个回弹的判断。
<Window x:Class="_3Dshow.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Demo" Height="441" Width="702" Background="LightGray" xmlns:System="clr-namespace:System;assembly=mscorlib"> <Grid PreviewMouseDown="_view_mousedown" PreviewMouseMove="_view_mousemove" PreviewMouseUp="_view_mouseup" > <Border Background="LightGray" Padding="2" Margin="0,-41,0,-40"> <Viewport3D x:Name="_view" > </Viewport3D> </Border> </Grid> </Window>
xmal,很简单 一个viewport3D,还有就是鼠标事件,这里如果你深入研究,会发现比较有意思的事情,路由事件!
从grid 路由到viewground,如果外面再嵌套一个canvas,会更清晰。
个人认为路由事件比较扯淡的是,我想让grid处理不让viewport3d处理,或者又想让grid处理又想让viewport3d处理,这是很有意思的事情。
好,这里不多啰嗦,上代码
#region 全局函数
// Queue<double>[,] sum_queue; double[,] sum_queue = new double[5, 2]; PerspectiveCamera _camera = null; bool ismousedown = false; // TimeSpan timspan; Point startPoint, currentPoint, endPoint; string[] fileList; double[,] sum_list; int _b = 0; DispatcherTimer sub_time = new DispatcherTimer(); DispatcherTimer sub_time1 = new DispatcherTimer(); private static DependencyProperty TranslatePosProperty = DependencyProperty.Register( "TranslatePos", typeof(double), typeof(Window1), new PropertyMetadata((double)0, new PropertyChangedCallback(DragPosChanged))); #endregion
一个依赖属性,两个dispatchertimer,一个用于控制拖拽动画,一个用于托抓完毕后的回弹效果,通过animation来改变依赖属性,进一步达到控制整个页面的效果。
依赖属性的回测事件(我自己把这种回传事件称之为回测事件,个人喜好)
#region temp
double _pos = 0; void PosChanged(double pos) { double delta = pos - _pos; _pos = pos; GetTran(delta); } #endregion
下面是核心代码,我用一个数组存放了所有的图片,图片的位置,图片的偏转角度,图片的缩放大小,图片在左边还是在右边的一个标识位,最后通过设置Transform 来改变图片,其实不能说是图片了,因为他是一个个元素,viewport的元素,这些元素自身有Transform 这个属性,所以直接用这个设置,我还没有找到用动画或者故事板控制的方法。
private void GetTran(double sum) { for (int i = 0; i < _view.Children.Count; i++) { #region point move #region 调整位置 sum_list[i, 1] += sum / 270; //angel if (sum > 0) { if (sum_list[i, 4] == -2) { sum_list[i, 3] += sum / 2000; } else if (sum_list[i, 4] == 0) { sum_list[i, 3] -= sum / 2000; } else if (sum_list[i, 4] == 2) { sum_list[i, 3] -= sum / 2000; } } else { if (sum_list[i, 4] == -2) { sum_list[i, 3] += sum / 2000; } else if (sum_list[i, 4] == 0) { sum_list[i, 3] += sum / 2000; } else if (sum_list[i, 4] == 2) { sum_list[i, 3] -= sum / 2000; } } if (sum > 0) { if (sum_list[i, 2] == 0) { sum_list[i, 4] = 2; } sum_list[i, 2] -= sum / 10; if (sum_list[i, 2] == 0) { sum_list[i, 4] = 0; } } else if (sum < 0) { if (sum_list[i, 2] == 0) { sum_list[i, 4] = -2; } sum_list[i, 2] -= sum / 10; if (sum_list[i, 2] == 0) { sum_list[i, 4] = 0; } } #endregion Transform3DGroup tg = new Transform3DGroup(); tg.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), sum_list[i, 2]))); tg.Children.Add(new ScaleTransform3D(sum_list[i, 3], sum_list[i, 3], sum_list[i, 3])); tg.Children.Add(new TranslateTransform3D(sum_list[i, 1], 0, sum_list[i, 0])); _view.Children[i].Transform = tg; #endregion } Volidating(); }
最后会有一个校验,校验是让设置每个图片是否超标,以及设置他们到和初始相比较的状态
private void Volidating() { for (int i = 0; i < _view.Children.Count; i++) { if (sum_list[i, 3] >= 1) { sum_list[i, 1] = 0; sum_list[i, 3] = 1; sum_list[i, 2] = 0; sum_list[i, 4] = 0; int sum = 1; for (int j = i - 1; j >= 0; j--) { sum_list[j, 3] = 1 - (0.2) * sum; if (sum_list[j, 3] <= 0) { sum_list[j, 3] = 0; } sum_list[j, 2] = 40 * sum; sum_list[j, 1] = -1.5 * sum; sum++; } sum = 1; for (int j = i + 1; j < _view.Children.Count; j++) { sum_list[j, 3] = 1 - (0.2) * sum; if (sum_list[j, 3] <= 0) { sum_list[j, 3] = 0; } sum_list[j, 2] = 40 * sum * (-1); sum_list[j, 1] = 1.5 * sum; sum++; } break; } } }
当鼠标点击时候,我记录下一个坐标,鼠标移动时,我记录下一个坐标,鼠标起来时,我记录一个坐标,鼠标移动时,触发第一个timer,鼠标起来时,触发第二个timer。
这些就是基本思路,写的很随性,思维不缜密,10年11月时候花了一周时间写的,我并不是说我怎么怎么样,nb或者sb,只是有些怀念。
那时候研究wpf,一心要涉足这个方向,对于动画一知半解,wpf相对于winform是一个全新的东西,现在看这些代码,或许觉得摇头或者觉得垃圾,但是很怀念那时候还年轻的时候,用最笨的方法实现想要的东西,为此而加班至深夜。
有时候为了找一些问题,google出来,千篇一律,copy是常见,稍微带源码的都要注册,积分,很不喜欢把程序商品化,共享讨论才能有改进,所以就把之前的代码发来讨论一下,如有兴趣,可以继续改进。
(我们是拉风的程序员,不是屌丝)
谨祝福'那时候终日不知疲倦,反复坐在电脑旁测试,看着自己写出的东西,在心里自己对自己说:看,这是我写出来的东西。'又奔波不已的所有程序员。
源码:
files.cnblogs.com/fish124423/3Dshow.rar