wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)

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

你可能感兴趣的:(WPF)