2025-09-28 16:45:46 +08:00

194 lines
6.7 KiB
C#

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;
private EventHandler _renderHandler;
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;
UpdateLayoutWithAnimation();
// 启动进度条动画
var current = Images[_selectedIndex];
StartProgress(current);
}
}
private void StartProgress(CoverFlowItem item)
{
StopProgress();
_renderHandler = (s, e) =>
{
if (item.Progress < 1)
item.Progress += 0.005; // 每帧增加一点
else
item.Progress = 0;
};
CompositionTarget.Rendering += _renderHandler;
}
private void StopProgress()
{
if (_renderHandler != null)
{
CompositionTarget.Rendering -= _renderHandler;
_renderHandler = null;
}
}
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--;
}
}