168 lines
6.0 KiB
C#
168 lines
6.0 KiB
C#
using _3DTools;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Animation;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Media.Media3D;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
using System.Windows.Threading;
|
|
|
|
namespace Wpf_AiSportsMicrospace.MyUserControl
|
|
{
|
|
/// <summary>
|
|
/// CoverFlowControl1.xaml 的交互逻辑
|
|
/// </summary>
|
|
|
|
public partial class CoverFlowControl1 : UserControl
|
|
{
|
|
public ObservableCollection<CoverFlowItem> Images { get; set; } = new ObservableCollection<CoverFlowItem>();
|
|
private int _selectedIndex = 0;
|
|
|
|
public int SelectedIndex
|
|
{
|
|
get => _selectedIndex;
|
|
set
|
|
{
|
|
if (Images.Count == 0) return;
|
|
if (value < 0) _selectedIndex = Images.Count - 1;
|
|
else if (value >= Images.Count) _selectedIndex = 0;
|
|
else _selectedIndex = value;
|
|
|
|
for (int i = 0; i < Images.Count; i++)
|
|
{
|
|
Images[i].IsSelected = (i == _selectedIndex);
|
|
if (i == _selectedIndex) Images[i].Progress = 0;
|
|
}
|
|
|
|
UpdateLayoutWithAnimation();
|
|
}
|
|
}
|
|
|
|
public CoverFlowControl1()
|
|
{
|
|
InitializeComponent();
|
|
DataContext = this;
|
|
Loaded += (s, e) => UpdateLayoutWithAnimation(true);
|
|
|
|
var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(30) };
|
|
timer.Tick += (s, e) =>
|
|
{
|
|
if (Images.Count == 0) return;
|
|
var current = Images[_selectedIndex];
|
|
if (current.Progress < 1)
|
|
current.Progress += 0.01; // 调整速度
|
|
};
|
|
timer.Start();
|
|
}
|
|
|
|
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (sender is Border border)
|
|
{
|
|
var container = ItemsHost.ItemContainerGenerator.ContainerFromItem(border.DataContext) as ContentPresenter;
|
|
if (container != null)
|
|
{
|
|
int index = ItemsHost.ItemContainerGenerator.IndexFromContainer(container);
|
|
SelectedIndex = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateLayoutWithAnimation(bool instant = false)
|
|
{
|
|
double centerX = ActualWidth / 2;
|
|
double spacing = 180;
|
|
double sideScale = 0.8;
|
|
double centerScale = 1.2;
|
|
|
|
for (int i = 0; i < ItemsHost.Items.Count; i++)
|
|
{
|
|
var container = ItemsHost.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter;
|
|
if (container == null) continue;
|
|
|
|
var border = FindVisualChild<Border>(container);
|
|
if (border == null) continue;
|
|
|
|
var transformGroup = border.RenderTransform as TransformGroup;
|
|
var scale = transformGroup.Children[0] as ScaleTransform;
|
|
var translate = transformGroup.Children[1] as TranslateTransform;
|
|
|
|
double targetX;
|
|
double targetScale;
|
|
double targetOpacity;
|
|
|
|
if (i == SelectedIndex)
|
|
{
|
|
targetX = centerX - 75;
|
|
targetScale = centerScale;
|
|
targetOpacity = 1.0;
|
|
}
|
|
else if (i == SelectedIndex - 1 || (SelectedIndex == 0 && i == Images.Count - 1))
|
|
{
|
|
targetX = centerX - spacing - 75;
|
|
targetScale = sideScale;
|
|
targetOpacity = 1.0;
|
|
}
|
|
else if (i == SelectedIndex + 1 || (SelectedIndex == Images.Count - 1 && i == 0))
|
|
{
|
|
targetX = centerX + spacing - 75;
|
|
targetScale = sideScale;
|
|
targetOpacity = 1.0;
|
|
}
|
|
else
|
|
{
|
|
targetX = centerX - 75;
|
|
targetScale = sideScale;
|
|
targetOpacity = 0.0;
|
|
}
|
|
|
|
if (instant)
|
|
{
|
|
translate.X = targetX;
|
|
scale.ScaleX = scale.ScaleY = targetScale;
|
|
border.Opacity = targetOpacity;
|
|
}
|
|
else
|
|
{
|
|
translate.BeginAnimation(TranslateTransform.XProperty,
|
|
new DoubleAnimation(targetX, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() });
|
|
scale.BeginAnimation(ScaleTransform.ScaleXProperty,
|
|
new DoubleAnimation(targetScale, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() });
|
|
scale.BeginAnimation(ScaleTransform.ScaleYProperty,
|
|
new DoubleAnimation(targetScale, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() });
|
|
border.BeginAnimation(Border.OpacityProperty,
|
|
new DoubleAnimation(targetOpacity, TimeSpan.FromMilliseconds(400)));
|
|
}
|
|
}
|
|
}
|
|
|
|
private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
|
|
{
|
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
|
{
|
|
var child = VisualTreeHelper.GetChild(obj, i);
|
|
if (child is T target) return target;
|
|
var result = FindVisualChild<T>(child);
|
|
if (result != null) return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void SlideLeft() => SelectedIndex++;
|
|
public void SlideRight() => SelectedIndex--;
|
|
}
|
|
|
|
}
|