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));
}
}
}

在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>


/// <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();
}

最后上一个简单的Demo:WPF_ImageShow
WPF 图片浏览 伪3D效果的更多相关文章
- flash 逐字,逐行歌词实现,添加伪3D效果
项目结构: 效果如图: 项目为公司项目,下载人员禁止用于商业项目中. 项目开发工具:FlashDevelop 点击下载
- wpf图片切换,幻灯效果
xaml: <Window x:Class="WpfApplication1.PicShow" xmlns="http://schemas.microsoft.co ...
- 实现一个图片轮播-3d播放效果
前言:最近在做一个音乐播放器,首页要做一个图片轮播,看了bootstrap的carousel插件以及移动端的swipe.js库,都是平面图片轮播的效果,所以自己想着实现类似网易云app里那种3d图片轮 ...
- 2.5D(伪3D)站点可视化第一弹
楔子 最近要做一个基站站点的可视化呈现项目. 我们首先尝试的是三维的可视化技术来程序,但是客户反馈的情况是他们的客户端电脑比较差,性能效率都会不好,甚至有的还是云主机. 因此我们先做了一个性能比较极致 ...
- wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)
原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码) pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依 ...
- WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现
原文:WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放.图片立体轮播.图片倒影立体滚动)效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...
- 在WPF中使用PlaneProjection模拟动态3D效果
原文:在WPF中使用PlaneProjection模拟动态3D效果 虽然在WPF中也集成了3D呈现的功能,在简单的3D应用中,有时候并不需要真实光影的3D场景.毕竟使用3D引擎会消耗很多资源,有时候使 ...
- Android 高级UI设计笔记14:Gallery(画廊控件)之 3D图片浏览
1. 利用Gallery组件实现 3D图片浏览器的功能,如下: 2. 下面是详细的实现过程如下: (1)这里我是测试性代码,我的图片是自己添加到res/drawable/目录下的,如下: 但是开发中不 ...
- 3d效果的图片轮播
CSS3的3d变换 CSS3给我们提供了一个新的功能,那就是3d变换.3d变换和2d变换的基本API函数类似,只不过多了些在Z轴上的操作,不难使用. 但是,为了让元素拥有3d变换的功能,我们需要给他的 ...
随机推荐
- 五、Linux/UNIX操作命令积累【cp、mv、cat、grep、ps】
在使用Linux/UNIX下,常常会使用文本界面去设置系统或操作系统,作者本人在工作的过程也在不断接触这方面的命令,所以为此特酝酿.准备.開始了本文的编写.本文主要记录自己平时遇到的一些Linux/U ...
- 使用Boost库中的组件进行C++内存管理
C++标准库中的auto_ptr,智能指针,部分的解决了获取资源自动释放的问题 在Boost中,提供了6中智能指针:scoped_ptr, scoped_array, shared_ptr, shar ...
- sql使用存储过程和交易
在过去的一年.学习数据库的时候学校有存储过程.永远只是知道一些理论,我不知道怎么用.时隔一年,最终找到怎样使用存储过程了. 在机房收费系统中.有些操作.须要多次运行sql语句,多次运行完毕才算是完毕这 ...
- poj3281(最大流)
传送门:Dining 题意:一些牛,一些食物,一些饮料,每头牛都有其喜欢的几种食物和几种饮料,求最多能给多少头牛即找到食物又找到饮料~也就是有多少个 牛---食物---饮料 的匹配,而且满足一一匹配, ...
- 从零开始,使用python快速开发web站点(1)
环境:ubuntu 12.04 python版本: 2.73 ok,首先,既然是从零开始,我们需要的是一台可以运行的python的计算机环境,并且假设你已经安装好了python, (ubuntu 或 ...
- Docker 用法总结之:管理工具 shipyard 的具体使用指南
Docker 的命令行就已经非常好用了,假设非要加上基于 Web 的管理界面的话也有一些选择,如 DockerUI (Angular.js), Dockland (Ruby), Shipyard (P ...
- unix解释器文件详解
exec执行普通文件和解释器文件的区别 2014-11-15 23:52:45 分类: LINUX exec执行普通文件和解释器文件的区别 ——lvyilong316 1. 从一个问题开始 首先要从项 ...
- 获取Enum枚举值描述的几法方法
原文:获取Enum枚举值描述的几法方法 1.定义枚举时直接用中文 由于VS对中文支持的很不错,所以很多程序员都采用了此方案. 缺点:1.不适合多语言 2.感觉不太完美,毕竟大部分程序员大部分代码都使用 ...
- hdu3555(数位dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题意:求区间[a,b]内包含有'49'的数的总个数. 分析:dp[pos][0]表示到第pos位 ...
- MySQL 全角转换为半角
序言: 用户注冊时候,录入了全角手机号码,所以导致短信系统依据手机字段发送短信失败.如今问题来了,怎样把全角手机号码变成半角手机号码? 1.手机号码全角转换成半角先查询出来全角半角都存在 ...