• WPF 图片浏览 伪3D效果


    首先上效果图:

    因项目要求,需要把图片以“好看”、“炫”的效果展示出来,特地研究了一下WPF关于3D方面的制作,奈何最终成果只是能够画出一个立方体并使之旋转。

    项目时间仅剩两天,只好放弃3D另找出路,于是就想起了Flash中各种“炫丽”的动画效果,图片按椭圆排列,并且旋转。

    于是开始代码,然后发现关于椭圆啊、正玄余玄、x,y,r等等数学知识都忘得光光了,仅有思路没有进展,无奈之下开始百度恶补数学知识。图形变换、3D是很考验数学知识的,本人对于3D方面的学习就败在数学之下,高中数学学的还不错的,现在……哎,不提也罢。

    然后找到这么一篇博文——javascript-按圆形排列DIV元素(三)实例---- 图片按椭圆形转动,是js代码,在此感谢这位船长op大大的无私奉献。

    下面正式上代码:

    定义ImageInfo类,实现INotifyPropertyChanged接口,属性没有写说明,不过看名称我想各位也能知道是什么含义了。

    public class ImageInfo : INotifyPropertyChanged
        {
            private int _zIndex;
    
            public int ZIndex
            {
                get { return _zIndex; }
                set
                {
                    if (value != _zIndex)
                    {
                        _zIndex = value;
                        this.NotifyPropertyChanged("ZIndex");
                    }
                }
            }
            private double _left;
    
            public double Left
            {
                get { return _left; }
                set
                {
                    if (value != _left)
                    {
                        _left = value;
                        this.NotifyPropertyChanged("Left");
                    }
                }
            }
            private double _top;
    
            public double Top
            {
                get { return _top; }
                set
                {
                    if (value != _top)
                    {
                        _top = value;
                        this.NotifyPropertyChanged("Top");
                    }
                }
            }
            private double _width;
    
            public double Width
            {
                get { return _width; }
                set
                {
                    if (value != _width)
                    {
                        _width = value;
                        this.NotifyPropertyChanged("Width");
                    }
                }
            }
            private double _height;
    
            public double Height
            {
                get { return _height; }
                set
                {
                    if (value != _height)
                    {
                        _height = value;
                        this.NotifyPropertyChanged("Height");
                    }
                }
            }
    
            private double _opacity = 1.0;
    
            public double Opactity
            {
                get { return _opacity; }
                set 
                {
                    if (value != _opacity)
                    {
                        _opacity = value;
                        this.NotifyPropertyChanged("Opactity");
                    }
                }
            }
    
            private string _imagePath;
    
            public string ImagePath
            {
                get { return _imagePath; }
                set
                {
                    if (value != _imagePath)
                    {
                        _imagePath = value;
                        this.NotifyPropertyChanged("ImagePath");
                    }
                }
            }
    
            public ImageInfo(string path)
            {
                this.ImagePath = path;
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void NotifyPropertyChanged(String propertyName)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (null != handler)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    ViewModel Code

    在xaml中binding ImageInfo 中的对应的属性,在后台代码中使用计时器来定时更改ImageInfo中的属性,当属性值发生改变时就会通知到界面,于是就实现了动画效果了。

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WPF_ImageShow" x:Class="WPF_ImageShow.MainWindow"
            Title="MainWindow" Height="600" Width="800" >
        <Window.Resources>
            <local:DoubleConverter x:Key="doubleConverter"/>
        </Window.Resources>
        <Grid>
            <ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" Loaded="lv_Loaded"
                ScrollViewer.VerticalScrollBarVisibility="Disabled" x:Name="lv" Background="Black">
                <!--<ListView.ItemTemplate>
                    <DataTemplate>
                        <Border>
                            <StackPanel>
                                <Image Source="{Binding ImagePath, Mode=OneWay}" x:Name="img" 
                                                Stretch="UniformToFill" Width="{Binding Width, Mode=OneWay}"
                                                Height="{Binding Height, Mode=OneWay}"/>
                                <Rectangle RenderTransformOrigin="1,0.5"  Height="{Binding Height, Converter={StaticResource doubleConverter}, Mode=OneWay}">
                                    <Rectangle.Fill>
                                        <VisualBrush Visual="{Binding ElementName=img}" />
                                    </Rectangle.Fill>
                                    <Rectangle.RenderTransform>
                                        <TransformGroup>
                                            <ScaleTransform ScaleY="-1" />
                                        </TransformGroup>
                                    </Rectangle.RenderTransform>
                                    <Rectangle.OpacityMask>
                                        <LinearGradientBrush StartPoint="0,0"   EndPoint="0,1">
                                            <GradientStop Offset="0.3"     Color="Transparent" />
                                            <GradientStop Offset="1"   Color="#44000000" />
                                        </LinearGradientBrush>
                                    </Rectangle.OpacityMask>
                                </Rectangle>
                            </StackPanel>
                        </Border>
                    </DataTemplate>
                </ListView.ItemTemplate>-->
                <ListView.Resources>
                    <Style TargetType="{x:Type ListViewItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ListViewItem}" >
                                    <Border>
                                        <StackPanel>
                                            <Image Source="{Binding ImagePath, Mode=OneWay}" x:Name="img" 
                                                Stretch="UniformToFill" Width="{Binding Width, Mode=OneWay}"
                                                Height="{Binding Height, Mode=OneWay}"/>
                                            <Rectangle RenderTransformOrigin="1,0.5"  Height="{Binding Height, Converter={StaticResource doubleConverter}, Mode=OneWay}">
                                                <Rectangle.Fill>
                                                    <VisualBrush Visual="{Binding ElementName=img}" />
                                                </Rectangle.Fill>
                                                <Rectangle.RenderTransform>
                                                    <TransformGroup>
                                                        <ScaleTransform ScaleY="-1" />
                                                    </TransformGroup>
                                                </Rectangle.RenderTransform>
                                                <Rectangle.OpacityMask>
                                                    <LinearGradientBrush StartPoint="0,0"   EndPoint="0,1">
                                                        <GradientStop Offset="0.3"     Color="Transparent" />
                                                        <GradientStop Offset="1"   Color="#44000000" />
                                                    </LinearGradientBrush>
                                                </Rectangle.OpacityMask>
                                            </Rectangle>
                                        </StackPanel>
                                    </Border>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Opacity" Value="{Binding Opactity, Mode=OneWay}"/>
                        <Setter Property="Canvas.Left" Value="{Binding Left, Mode=OneWay}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Top, Mode=OneWay}"/>
                        <Setter Property="Panel.ZIndex" Value="{Binding ZIndex, Mode=OneWay}"/>
                    </Style>
                </ListView.Resources>
                <ListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ListView.ItemsPanel>
            </ListView>
        </Grid>
    </Window>
    XAML Code
     /// <summary>
            /// 设置动画
            /// </summary>
            void Run()
            {
                //动画速率
                double speed = 0.0;
                //定时器,定时修改ImageInfo中各属性,从而实现动画效果
                DispatcherTimer timer = new DispatcherTimer();
                //时间间隔
                timer.Interval = TimeSpan.FromMilliseconds(100);
                timer.Tick += (ss, ee) =>
                {
                    #region
                    //设置圆心x,y
                    double centerX = this.ActualWidth / 2;
                    double centerY = this.ActualHeight / 2 - 50;//减去适当的值,因为会设置最下面的图片最大,上面的图片较小
    
                    //设置图片最大的宽、高
                    double maxWidth = 300;
                    double maxHeight = 200;
    
                    //设置椭圆的长边和短边
                    double a = centerX - maxWidth / 2.0;
                    double b = centerY - maxHeight / 2.0;
    
                    //运动一周后恢复为0
                    speed = speed < 360 ? speed : 0.0;
                    //运运的速度 此“增值”和  timer.Interval对动画的流畅性有影响
                    speed += 0.5;
                    //运动距离,即运动的弧度数;
                    var ainhd = speed * Math.PI / 180;
                    //每个图片之间相隔的角度
                    var angle = (360.0 / data.Count) * Math.PI / 180.0;
                    //图片序号
                    int index = 0;
                    foreach (var img in data)
                    {
                        //最下面一张图ZIndex最大,Opacity最大,长宽最大
    
                        img.ZIndex = (int)img.Top;
                        //当前图片与最下面一张图片的Y的比值
                        var allpers = img.Top / (centerY + b);
                        //不要小于0.2,太小了就看不见了,可以适当调整
                        allpers = Math.Max(0.2, allpers);
                        //设置图片大小
                        img.Width = allpers * maxWidth;
                        img.Height = allpers * maxHeight;
                        //设置透明度
                        img.Opactity = Math.Max(allpers * 1.5, 0.4);
    
                        //公式:x=sin * a //+ centerX因为默认wpf默认左上角为坐标原点;//- img.Width / 2.0是以图片中心点作为运动轨迹
                        img.Left = Math.Sin((angle * index + ainhd)) * a + centerX - img.Width / 2.0;//x=sin * a
                        //y=cos * b
                        img.Top = Math.Cos((angle * index + ainhd)) * b + centerY - img.Height / 2.0;
    
                        index++;
                    }
                    #endregion
                };
                //启动计时器,开始动画
                timer.Start();
            }
    
            private void lv_Loaded(object sender, RoutedEventArgs e)
            {
                //准备数据源 ObservableCollection<T>
                data = new ObservableCollection<ImageInfo>();
                //获取程序所在目录中的images文件夹
                DirectoryInfo di = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory + "images");
                //添加此目录中的图片文件到data中
                foreach (var file in di.GetFiles())
                {
                    //验证是否为图片文件 (可以写一个方法来进行验证,此处仅支持jpg和png)
                    if (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png")
                    {
                        data.Add(new ImageInfo(file.FullName));
                    }
                }
                //设置ListView的ItemsSource
                lv.ItemsSource = data;
    
                Run();
            }
    View Code

    最后上一个简单的Demo:WPF_ImageShow

  • 相关阅读:
    Atitit fms Strait (海峡) lst 数据列表目录1. 4大洋 12. 著名的海大约40个,总共约55个海 13. 海区列表 23.1. 、波利尼西亚(Polynesia,
    Atitit trave islands list 旅游资源列表岛屿目录1. 东南亚著名的旅游岛屿 21.1. Cjkv 日韩 冲绳 琉球 济州岛 北海道 21.2. 中国 涠洲岛 南澳
    Atitit Major island groups and archipelagos 主要的岛群和群岛目录资料目录1. 岛群 波利尼西亚(Polynesia, 美拉尼西亚(Melanesia,
    Atitit glb 3tie city lst 三线城市列表 数据目录1. 全球范围内约90个城市 三线 12. 世界性三线城市全球共
    Atitit glb 1tie 2tie city lst 一二线城市列表数据约50个一线城市Alpha ++ 阿尔法++,,London 伦敦,,New York 纽约,,Alpha +
    Attit 现代编程语言重要特性目录第一章 类型系统 基本三大类型 2第一节 字符串 数字 bool 2第二节 推断局部变量 2第三节 动态类型 2第二章 可读性与开发效率 简单性 2
    Atitit 未来数据库新特性展望目录1. 统一的翻页 21.1. 2 Easy Top-N
    使用Chrome DevTools(console ande elements panel)进行xpath/css/js定位
    chrome -console妙用之定位xpath/js/css
    表达式树之构建Lambda表达式
  • 原文地址:https://www.cnblogs.com/LCHL/p/3078785.html
Copyright © 2020-2023  润新知