Silverlight——简单3D效果的探究
3D:
在MSDN上有个关于silverlight的3D展示,点击两边的图片时,图片转换会出先立体视觉动画效果:
这个效果看上去很炫,但偏偏就这个实例MSDN上不给代码!郁闷啊。
立体感与3D:
既然没有那我就自己来。虽学习SL有段时间了,但多是在内部数据方面。虽然也看到过别人做出的3D效果的作品,但就觉的很炫,也就过过
眼。既不知道如何实现这样的效果的,也没想过原理。偶然看到一张很让人纠结的图片:
我还为这个三角形是站着的还是躺着的,思考了半天。其实我也并不清楚这种“3D”和《阿凡达》要带眼镜的“3D”那个更确切。
其实这个利用的是人的视觉,让人产生一种立体的感觉。
布局:
回到那个例子上,当然这些图片都是平面的。下面用数据说明,如何让平面的看起来
像个立体的:
旁边的是刚开始我设计的动作变化。下面还有实验时候的布局代码,并不完全,但已经有了思路了:
代码<Rectangle x:Name="AR" Tag="left" Width="200" Height="250" Canvas.Top="20" Canvas.Left="50" Canvas.ZIndex="3" MouseLeftButtonDown="btnMouseLeftButtonDown">
<Rectangle.Projection>
<PlaneProjection x:Name="AP" RotationY="-60"></PlaneProjection>
</Rectangle.Projection>
<Rectangle.Fill>
<ImageBrush x:Name="Aimg" ImageSource="/SLDemo3D;component/florian.jpg">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BR" Tag="mid" Width="200" Height="250" Canvas.Top="20" Canvas.Left="300" Canvas.ZIndex="2" MouseLeftButtonDown="btnMouseLeftButtonDown">
<Rectangle.Projection>
<PlaneProjection x:Name="BP" RotationY="0"></PlaneProjection>
</Rectangle.Projection>
<Rectangle.Fill>
<ImageBrush x:Name="Bimg" ImageSource="/SLDemo3D;component/jareck.jpg">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="CR" Tag="right" Width="200" Height="250" Canvas.Top="20" Canvas.Left="550" Canvas.ZIndex="1" MouseLeftButtonDown="btnMouseLeftButtonDown">
<Rectangle.Projection>
<PlaneProjection x:Name="CP" RotationY="60"></PlaneProjection>
</Rectangle.Projection>
<Rectangle.Fill>
<ImageBrush x:Name="Cimg" ImageSource="/SLDemo3D;component/kamil.jpg">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>就是用了:<Rectangle.Projection>
<PlaneProjection x:Name="CP" RotationY="60"></PlaneProjection>
</Rectangle.Projection>
使图片产生侧面立体的效果,简单吧。(为了看起来更逼真,您可以将中间一幅设置稍大点)这样就会有:
动画:
下面最主要的问题就是如何设定动画。将动画分解,其实就是两部:
1,图片视角的动画
2,图片位置的动画
这样就好办了,利用<Storyboard >
<DoubleAnimation Storyboard.TargetName=""Storyboard.TargetProperty=""From="" To="" Duration="">
</DoubleAnimation>
</Storyboard>
很容易就实现动画效果了。只需要将这两个动画组合起来,同时进行。就会实现类似MSDN上的效果了。
代码<Canvas.Resources>
<Storyboard x:Name="myStoryboard" Completed="myStoryboard_Completed">
<!--图片的旋转-->
<DoubleAnimation x:Name="daAP" Storyboard.TargetName="AP"
Storyboard.TargetProperty="RotationY"
From="-60" To="0" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daBP" Storyboard.TargetName="BP"
Storyboard.TargetProperty="RotationY"
From="0" To="60" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daCP" Storyboard.TargetName="CP"
Storyboard.TargetProperty="RotationY"
From="60" To="-60" Duration="0:0:1"></DoubleAnimation>
<!--图片换位-->
<DoubleAnimation x:Name="daAR" Storyboard.TargetName="AR"
Storyboard.TargetProperty="(Canvas.Left)"
From="50" To="300" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daBR" Storyboard.TargetName="BR"
Storyboard.TargetProperty="(Canvas.Left)"
From="300" To="550" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daCR" Storyboard.TargetName="CR"
Storyboard.TargetProperty="(Canvas.Left)"
From="550" To="50" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
<Storyboard x:Name="myStoryboard2" Completed="myStoryboard2_Completed">
<!--图片的旋转-->
<DoubleAnimation x:Name="daAP2" Storyboard.TargetName="AP"
Storyboard.TargetProperty="RotationY"
From="-60" To="60" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daBP2" Storyboard.TargetName="BP"
Storyboard.TargetProperty="RotationY"
From="0" To="-60" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daCP2" Storyboard.TargetName="CP"
Storyboard.TargetProperty="RotationY"
From="60" To="0" Duration="0:0:1"></DoubleAnimation>
<!--图片换位-->
<DoubleAnimation x:Name="daAR2" Storyboard.TargetName="AR"
Storyboard.TargetProperty="(Canvas.Left)"
From="50" To="550" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daBR2" Storyboard.TargetName="BR"
Storyboard.TargetProperty="(Canvas.Left)"
From="300" To="50" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation x:Name="daCR2" Storyboard.TargetName="CR"
Storyboard.TargetProperty="(Canvas.Left)"
From="550" To="300" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</Canvas.Resources>代码中设定了两个动画效果,一个是图片向左旋转的,一个是向右旋转的。
实验了一下,基本上实现了“3D”效果。
进一步的改进:
似乎我们的目的达到了,但是很多地方还要改进。首先就是我们图片只会向左或向右移动一次,然后就是重复动画了,这当然是不行的。
所以首先动态设定图片立体视觉的参数:
代码//旋转参数
double tempdaAP = (double)daAP2.From;
daAP2.From =daAP2.To;
daBP2.To=daAP2.From ;
daBP2.From= daBP2.To;
daCP2.To=daBP2.From ;
daCP2.From=daCP2.To;
daCP2.To=tempdaAP;还有动画位移的参数:
代码//坐标参数
double tempdaAR = (double)daAR2.From;
daAR2.From=daAR2.To;
daBR2.To= daAR2.From;
daBR2.From = daBR2.To;
daCR2.To= daBR2.From;
daCR2.From= daCR2.To;
daCR2.To= tempdaAR;细心的您一定会发现这只是向左边移动时的情况,向右移动的时候上面的两组代码又会不一样!
同样的问题还在图片的ZIndex参数上:
代码//zindex参数
int tempindex = Canvas.GetZIndex(AR);
Canvas.SetZIndex(AR, Canvas.GetZIndex(BR));
Canvas.SetZIndex(BR, Canvas.GetZIndex(CR));
Canvas.SetZIndex(CR, tempindex);
string temptag = AR.Tag.ToString();这是向右移动时Zindex修改情况,但向左时的又是另一情况!
还有个问题,就是如何判断图片向左还是向右?跟据上面的代码,可以用同样的方式处理这个问题。
CR.MouseLeftButtonDown += new MouseButtonEventHandler(btnMouseLeftButtonDown);
CR.MouseLeftButtonDown -= new MouseButtonEventHandler(btnMouseLeftButtonDown);
为不同位置的图片移除和绑定不同的事件。这是方法之一,同样还可以这样做:
为每个图片设定tag,用于存放位置的信息。然后根据触发事件的sender判断当前图片的位置。动画完成后利用上面轮换的方法重新
设定图片的tag。(因为name不能随便修改,所以使用tag)
//tag用于判定动画
string temptag = AR.Tag.ToString();
AR.Tag=BR.Tag;
BR.Tag = CR.Tag;
CR.Tag = temptag;
结束:
根据以上的信息,我想您应该明白我是如何设计和实现这个MSDN的“3D”效果了。别高兴的太早,还有很多东西需要完善的。比如:
如何让判断左右移动代码更简洁?如何处理动画未完成时,用户又点击动画了?如何处理以上的代码的顺序,是在移动前还是在移动完成
后?等等等。以上问题我都实现和优化了,但不知与MSDN上的代码有多大的差距呢?
我建议您自己思考一下,因为我在设计的时候很多东西有的方法并不容易实现的,还有的处理方法可能会是多样的。
OK,这就是一个从未见识过这方面内容和没有任何参考的人关于简单“3D”实现的思考。各位不要见笑。
如果您有何这方面的经验和新的想法,不妨说出来,让我也学习学习。