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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM