原文連結:https://www.cnblogs.com/zhouyinhui/archive/2007/09/27/908213.html
1、效果
蘋果iTunes播放器的CoverFlow效果羨煞旁人,不過有了WPF,我們也可以輕松實作哈,今天費了半天的時間終于搞定,呵呵…
程式取的是使用者" 我的圖檔"檔案夾下的*.jpg圖檔,你可以修改代碼中的路徑或在"我的圖檔"檔案夾下放幾張jpg圖檔就可以看到效果了
圖檔是使用3DTools 提供的2D到3D映射的方式貼圖上去的,每張圖檔都帖在一個3D模型上,我們隻需要讓程式來安排這些模型的擺放位置就可以了
3D模型的擺放是按照如下方法進行的,其中3個傳出參數angle指定模型源Y軸的旋轉角度,offsetX指定模型的X軸方向上的平移量,offsetZ指定模型在Z軸方向上的平移量
/// <summary>
/// 依照InteractiveVisual3D在清單中的序号來變換其位置等
/// </summary>
/// <param name="index">在清單中的序号</param>
/// <param name="midIndex">清單中被作為中間項的序号</param>
private void GetTransformOfInteractiveVisual3D(int index, double midIndex, out double angle, out double offsetX, out double offsetZ)
{
double disToMidIndex = index - midIndex;
//旋轉,兩翼的圖檔各旋轉一定的度數
angle = 0;
if (disToMidIndex < 0)
{
angle = this.ModelAngle;//左邊的旋轉N度
}
else if (disToMidIndex > 0)
{
angle = (-this.ModelAngle);//右邊的旋轉-N度
}
//平移,兩翼的圖檔逐漸向X軸負和正兩個方向展開
offsetX = 0;//中間的不平移
if (Math.Abs(disToMidIndex) <= 1)
{
offsetX = disToMidIndex * this.MidModelDistance;
}
else if (disToMidIndex != 0)
{
offsetX = disToMidIndex * this.XDistanceBetweenModels + (disToMidIndex > 0 ? this.MidModelDistance : -this.MidModelDistance);
}
//兩翼的圖檔逐漸向Z軸負方向移動一點,造成中間突出(離觀衆較近的效果)
offsetZ = Math.Abs(disToMidIndex) * -this.ZDistanceBetweenModels;
}
點選圖檔或指定目前應該被突出顯示的圖檔時的動畫效果是這樣實作的,先使用上面的方法計算出決定模型位置的幾個便量的新值(即上面的幾個傳出參數),然後在使用動畫(DoubleAnimation)讓這幾個值由舊值過度到新值.
/// <summary>
/// 重新布局3D内容
/// </summary>
private void ReLayoutInteractiveVisual3D()
{
int j=0;
for (int i = 0; i < this.viewport3D.Children.Count; i++)
{
InteractiveVisual3D iv3d = this.viewport3D.Children[i] as InteractiveVisual3D;
if(iv3d != null)
{
double angle = 0;
double offsetX = 0;
double offsetZ = 0;
this.GetTransformOfInteractiveVisual3D(j++, this.CurrentMidIndex,out angle,out offsetX,out offsetZ);
NameScope.SetNameScope(this, new NameScope());
this.RegisterName("iv3d", iv3d);
Duration time = new Duration(TimeSpan.FromSeconds(0.3));
DoubleAnimation angleAnimation = new DoubleAnimation(angle, time);
DoubleAnimation xAnimation = new DoubleAnimation(offsetX, time);
DoubleAnimation zAnimation = new DoubleAnimation(offsetZ, time);
Storyboard story = new Storyboard();
story.Children.Add(angleAnimation);
story.Children.Add(xAnimation);
story.Children.Add(zAnimation);
Storyboard.SetTargetName(angleAnimation, "iv3d");
Storyboard.SetTargetName(xAnimation, "iv3d");
Storyboard.SetTargetName(zAnimation, "iv3d");
Storyboard.SetTargetProperty(
angleAnimation,
new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"));
Storyboard.SetTargetProperty(
xAnimation,
new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)"));
Storyboard.SetTargetProperty(
zAnimation,
new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetZ)"));
story.Begin(this);
}
}
}