wpf的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是常见,稍微带源码的都要注册,积分,很不喜欢把程序商品化,共享讨论才能有改进,所以就把之前的代码发来讨论一下,如有兴趣,可以继续改进。
(我们是拉风的程序员,不是屌丝)
谨祝福'那时候终日不知疲倦,反复坐在电脑旁测试,看着自己写出的东西,在心里自己对自己说:看,这是我写出来的东西。'又奔波不已的所有程序员。