顶顶顶顶
This commit is contained in:
parent
82d2a5fe6b
commit
be337abd61
@ -2,10 +2,8 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
|
||||
Title="CoverFlow Demo" Height="400" Width="800">
|
||||
Title="Home" Height="400" Width="800">
|
||||
<Grid>
|
||||
<!--<local:CoverFlowControl x:Name="coverFlow"/>-->
|
||||
|
||||
<local:CoverFlowControl1 x:Name="coverFlow1"/>
|
||||
<local:CoverFlowControl x:Name="coverFlow" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@ -2,12 +2,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Shapes;
|
||||
using System.IO;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using Wpf_AiSportsMicrospace.MyUserControl;
|
||||
|
||||
namespace Wpf_AiSportsMicrospace
|
||||
@ -21,20 +23,18 @@ namespace Wpf_AiSportsMicrospace
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
string projectRoot = System.IO.Path.Combine(AppContext.BaseDirectory, @"..\..\..");
|
||||
string albumPath = System.IO.Path.Combine(projectRoot, "Resources", "Img", "Album");
|
||||
string projectRoot = Path.Combine(AppContext.BaseDirectory, @"..\..\..");
|
||||
string albumPath = Path.Combine(projectRoot, "Resources", "Img", "Album");
|
||||
|
||||
ObservableCollection<CoverImage> images = new ObservableCollection<CoverImage>()
|
||||
{
|
||||
new CoverImage( System.IO.Path.Combine(albumPath, "1.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/1.jpg")),
|
||||
new CoverImage( System.IO.Path.Combine(albumPath, "2.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/2.jpg")),
|
||||
new CoverImage( System.IO.Path.Combine(albumPath, "3.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/3.jpg")),
|
||||
new CoverImage( System.IO.Path.Combine(albumPath, "4.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/4.jpg")),
|
||||
new CoverImage( System.IO.Path.Combine(albumPath, "5.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/5.jpg")),
|
||||
};
|
||||
// 转换为 Uri
|
||||
coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "1.jpg")));
|
||||
coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "2.jpg")));
|
||||
coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "3.jpg")));
|
||||
coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "4.jpg")));
|
||||
coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "5.jpg")));
|
||||
|
||||
// 设置 CoverFlow 图片s
|
||||
//coverFlow.SetImages(images, defaultSelectedIndex: 2);
|
||||
// 默认选中第3张
|
||||
coverFlow.SelectedIndex = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,103 +4,29 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
|
||||
mc:Ignorable="d" >
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
|
||||
<Style x:Key="ImageBorderStyle" TargetType="Border">
|
||||
<Setter Property="BorderThickness" Value="3"/>
|
||||
<Setter Property="Margin" Value="10"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="BorderBrush" Value="Transparent"/>
|
||||
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
|
||||
<Setter Property="RenderTransform">
|
||||
<Setter.Value>
|
||||
<ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSelected}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX"
|
||||
To="1.2" Duration="0:0:0.3"/>
|
||||
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY"
|
||||
To="1.2" Duration="0:0:0.3"/>
|
||||
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color"
|
||||
To="Red" Duration="0:0:0.3"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX"
|
||||
To="0.8" Duration="0:0:0.3"/>
|
||||
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY"
|
||||
To="0.8" Duration="0:0:0.3"/>
|
||||
<ColorAnimation Storyboard.TargetProperty="BorderBrush.Color"
|
||||
To="Transparent" Duration="0:0:0.3"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<ItemsControl x:Name="VisibleImagesControl">
|
||||
Height="300" Width="600">
|
||||
<Grid ClipToBounds="True" Background="Transparent">
|
||||
<ItemsControl x:Name="ItemsHost" ItemsSource="{Binding Images, RelativeSource={RelativeSource AncestorType=UserControl}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
<Canvas/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<!-- 主图片 -->
|
||||
<Border Style="{StaticResource ImageBorderStyle}" MouseLeftButtonDown="Image_MouseLeftButtonDown">
|
||||
<Image Source="{Binding Path}" Width="150" Height="200"/>
|
||||
<Border x:Name="ImageContainer" RenderTransformOrigin="0.5,0.5"
|
||||
MouseLeftButtonDown="Image_MouseLeftButtonDown">
|
||||
<Border.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform x:Name="scale" ScaleX="1" ScaleY="1"/>
|
||||
<TranslateTransform x:Name="translate" X="0" Y="0"/>
|
||||
</TransformGroup>
|
||||
</Border.RenderTransform>
|
||||
<Image Source="{Binding}" Stretch="UniformToFill" Width="150" Height="200"/>
|
||||
</Border>
|
||||
|
||||
<!-- 小徽章 logo,添加淡入淡出动画 -->
|
||||
<Image Source="{Binding BadgePath}" Width="50" Height="50"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Top"
|
||||
Margin="0,-25,0,0">
|
||||
<Image.Style>
|
||||
<Style TargetType="Image">
|
||||
<Setter Property="Opacity" Value="0"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSelected}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="Opacity"
|
||||
To="1" Duration="0:0:0.3"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="Opacity"
|
||||
To="0" Duration="0:0:0.3"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Image.Style>
|
||||
</Image>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
@ -11,6 +12,7 @@ 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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
@ -22,77 +24,118 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
|
||||
/// </summary>
|
||||
public partial class CoverFlowControl : UserControl
|
||||
{
|
||||
public ObservableCollection<CoverImage> AllImages { get; set; } = new ObservableCollection<CoverImage>();
|
||||
public ObservableCollection<CoverImage> VisibleImages { get; set; } = new ObservableCollection<CoverImage>();
|
||||
public ObservableCollection<Uri> Images { get; set; } = new ObservableCollection<Uri>();
|
||||
|
||||
private int selectedIndex = 0;
|
||||
private int _selectedIndex = 0;
|
||||
public int SelectedIndex
|
||||
{
|
||||
get => _selectedIndex;
|
||||
set
|
||||
{
|
||||
if (value < 0 || value >= Images.Count) return;
|
||||
_selectedIndex = value;
|
||||
UpdateLayoutWithAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
public CoverFlowControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
VisibleImagesControl.ItemsSource = VisibleImages;
|
||||
DataContext = this;
|
||||
Loaded += (s, e) => UpdateLayoutWithAnimation(true);
|
||||
}
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void SetImages(ObservableCollection<CoverImage> images, int defaultSelectedIndex = 0)
|
||||
{
|
||||
AllImages = images;
|
||||
selectedIndex = defaultSelectedIndex;
|
||||
UpdateVisibleImages();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is Border border && border.DataContext is CoverImage img)
|
||||
if (sender is Border border)
|
||||
{
|
||||
int index = AllImages.IndexOf(img);
|
||||
if (index >= 0)
|
||||
var container = ItemsHost.ItemContainerGenerator.ContainerFromItem(border.DataContext) as ContentPresenter;
|
||||
if (container != null)
|
||||
{
|
||||
selectedIndex = index;
|
||||
UpdateVisibleImages();
|
||||
int index = ItemsHost.ItemContainerGenerator.IndexFromContainer(container);
|
||||
SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisibleImages()
|
||||
private void UpdateLayoutWithAnimation(bool instant = false)
|
||||
{
|
||||
VisibleImages.Clear();
|
||||
for (int offset = -1; offset <= 1; offset++)
|
||||
double centerX = ActualWidth / 2;
|
||||
double spacing = 180;
|
||||
double sideScale = 0.8;
|
||||
double centerScale = 1.2;
|
||||
|
||||
for (int i = 0; i < ItemsHost.Items.Count; i++)
|
||||
{
|
||||
int idx = selectedIndex + offset;
|
||||
if (idx >= 0 && idx < AllImages.Count)
|
||||
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)
|
||||
{
|
||||
var img = AllImages[idx];
|
||||
img.IsSelected = offset == 0;
|
||||
VisibleImages.Add(img);
|
||||
targetX = centerX - 75;
|
||||
targetScale = centerScale;
|
||||
targetOpacity = 1.0;
|
||||
}
|
||||
else if (i == SelectedIndex - 1)
|
||||
{
|
||||
targetX = centerX - spacing - 75;
|
||||
targetScale = sideScale;
|
||||
targetOpacity = 1.0;
|
||||
}
|
||||
else if (i == SelectedIndex + 1)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CoverImage : INotifyPropertyChanged
|
||||
private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string BadgePath { get; set; }
|
||||
|
||||
private bool _isSelected;
|
||||
public bool IsSelected
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||||
{
|
||||
get => _isSelected;
|
||||
set { _isSelected = value; OnPropertyChanged(nameof(IsSelected)); }
|
||||
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 CoverImage(string path, string badgePath = null)
|
||||
{
|
||||
Path = path;
|
||||
BadgePath = badgePath;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
protected void OnPropertyChanged(string name) =>
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
<PackageReference Include="FFmpeg.AutoGen" Version="7.1.1" />
|
||||
<PackageReference Include="FFmpeg.AutoGen.Abstractions" Version="7.1.1" />
|
||||
<PackageReference Include="FFmpeg.AutoGen.Bindings.DynamicallyLoaded" Version="7.1.1" />
|
||||
<PackageReference Include="HandyControl" Version="3.5.1" />
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.ML" Version="4.0.2" />
|
||||
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.22.1" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user