This commit is contained in:
tanglong 2025-09-22 17:02:19 +08:00
parent 9a8c84245d
commit 0cc946d078
7 changed files with 186 additions and 160 deletions

View File

@ -3,83 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl" xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
Title="CoverFlow Demo" Height="400" Width="800"> Title="CoverFlow Demo" Height="400" Width="800">
<Window.Resources>
<!-- Bool 到 Visibility Converter -->
<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>
</Window.Resources>
<Grid> <Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> <local:CoverFlowControl x:Name="coverFlow"/>
<ItemsControl x:Name="VisibleImagesControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<!-- 主图片 -->
<Border Style="{StaticResource ImageBorderStyle}" MouseLeftButtonDown="Image_MouseLeftButtonDown">
<Image Source="{Binding Path}" Width="150" Height="200"/>
</Border>
<!-- 小徽章 logo -->
<Image Source="{Binding BadgePath}" Width="50" Height="50"
HorizontalAlignment="Center" VerticalAlignment="Top"
Margin="0,-25,0,0"
Visibility="{Binding IsSelected, Converter={StaticResource BoolToVisibilityConverter}}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid> </Grid>
</Window> </Window>

View File

@ -6,14 +6,9 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; 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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using System.IO;
using Wpf_AiSportsMicrospace.MyUserControl;
namespace Wpf_AiSportsMicrospace namespace Wpf_AiSportsMicrospace
{ {
@ -21,84 +16,25 @@ namespace Wpf_AiSportsMicrospace
/// Home.xaml 的交互逻辑 /// Home.xaml 的交互逻辑
/// </summary> /// </summary>
public partial class Home : Window public partial class Home : Window
{ {
// 所有图片
public ObservableCollection<CoverImage> AllImages { get; set; } = new ObservableCollection<CoverImage>();
public ObservableCollection<CoverImage> VisibleImages { get; set; } = new ObservableCollection<CoverImage>();
private int selectedIndex = 0;
public Home() public Home()
{ {
InitializeComponent(); InitializeComponent();
// 示例图片路径
string projectRoot = System.IO.Path.Combine(AppContext.BaseDirectory, @"..\..\.."); string projectRoot = System.IO.Path.Combine(AppContext.BaseDirectory, @"..\..\..");
string albumPath = System.IO.Path.Combine(projectRoot, "Resources", "Img", "Album"); string albumPath = System.IO.Path.Combine(projectRoot, "Resources", "Img", "Album");
string badgePath = System.IO.Path.Combine(projectRoot, "Resources", "Img", "Badge");
AllImages.Add(new CoverImage(System.IO.Path.Combine(albumPath, "1.jpg"), System.IO.Path.Combine(badgePath, "1.jpg"))); ObservableCollection<CoverImage> images = new ObservableCollection<CoverImage>()
AllImages.Add(new CoverImage(System.IO.Path.Combine(albumPath, "2.jpg"), System.IO.Path.Combine(badgePath, "2.jpg")));
AllImages.Add(new CoverImage(System.IO.Path.Combine(albumPath, "3.jpg"), System.IO.Path.Combine(badgePath, "3.jpg")));
AllImages.Add(new CoverImage(System.IO.Path.Combine(albumPath, "4.jpg"), System.IO.Path.Combine(badgePath, "4.jpg")));
AllImages.Add(new CoverImage(System.IO.Path.Combine(albumPath, "5.jpg"), System.IO.Path.Combine(badgePath, "5.jpg")));
VisibleImagesControl.ItemsSource = VisibleImages;
// 默认选中中间图片
selectedIndex = 2;
UpdateVisibleImages();
}
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Border border && border.DataContext is CoverImage img)
{ {
int index = AllImages.IndexOf(img); new CoverImage( System.IO.Path.Combine(albumPath, "1.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/1.jpg")),
if (index >= 0) 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")),
selectedIndex = index; new CoverImage( System.IO.Path.Combine(albumPath, "4.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/4.jpg")),
UpdateVisibleImages(); new CoverImage( System.IO.Path.Combine(albumPath, "5.jpg"), System.IO.Path.Combine(projectRoot, "Resources/Img/Badge/5.jpg")),
} };
}
}
private void UpdateVisibleImages() // 设置 CoverFlow 图片
{ coverFlow.SetImages(images, defaultSelectedIndex: 2);
VisibleImages.Clear();
for (int offset = -1; offset <= 1; offset++)
{
int idx = selectedIndex + offset;
if (idx >= 0 && idx < AllImages.Count)
{
var img = AllImages[idx];
img.IsSelected = offset == 0;
VisibleImages.Add(img);
}
}
} }
} }
}
public class CoverImage : INotifyPropertyChanged
{
public string Path { get; set; } // 主图路径
public string BadgePath { get; set; } // 小徽章路径
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set { _isSelected = value; OnPropertyChanged(nameof(IsSelected)); }
}
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));
}
}

View File

@ -4,9 +4,103 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl" xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
mc:Ignorable="d" mc:Ignorable="d" >
d:DesignHeight="450" d:DesignWidth="800"> <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> <Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<ItemsControl x:Name="VisibleImagesControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<!-- 主图片 -->
<Border Style="{StaticResource ImageBorderStyle}" MouseLeftButtonDown="Image_MouseLeftButtonDown">
<Image Source="{Binding Path}" 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> </Grid>
</UserControl> </UserControl>

View File

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,9 +22,77 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
/// </summary> /// </summary>
public partial class CoverFlowControl : UserControl public partial class CoverFlowControl : UserControl
{ {
public ObservableCollection<CoverImage> AllImages { get; set; } = new ObservableCollection<CoverImage>();
public ObservableCollection<CoverImage> VisibleImages { get; set; } = new ObservableCollection<CoverImage>();
private int selectedIndex = 0;
public CoverFlowControl() public CoverFlowControl()
{ {
InitializeComponent(); InitializeComponent();
VisibleImagesControl.ItemsSource = VisibleImages;
}
#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)
{
int index = AllImages.IndexOf(img);
if (index >= 0)
{
selectedIndex = index;
UpdateVisibleImages();
}
}
}
private void UpdateVisibleImages()
{
VisibleImages.Clear();
for (int offset = -1; offset <= 1; offset++)
{
int idx = selectedIndex + offset;
if (idx >= 0 && idx < AllImages.Count)
{
var img = AllImages[idx];
img.IsSelected = offset == 0;
VisibleImages.Add(img);
}
}
} }
} }
public class CoverImage : INotifyPropertyChanged
{
public string Path { get; set; }
public string BadgePath { get; set; }
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set { _isSelected = value; OnPropertyChanged(nameof(IsSelected)); }
}
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));
}
} }

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -16,7 +16,9 @@
<None Remove="Resources\Img\Album\5.jpg" /> <None Remove="Resources\Img\Album\5.jpg" />
<None Remove="Resources\Img\Badge\1.jpg" /> <None Remove="Resources\Img\Badge\1.jpg" />
<None Remove="Resources\Img\Badge\2.jpg" /> <None Remove="Resources\Img\Badge\2.jpg" />
<None Remove="Resources\Img\Badge\3.jpg" />
<None Remove="Resources\Img\Badge\3.png" /> <None Remove="Resources\Img\Badge\3.png" />
<None Remove="Resources\Img\Badge\4.jpg" />
<None Remove="Resources\Img\Badge\4.png" /> <None Remove="Resources\Img\Badge\4.png" />
<None Remove="Resources\Img\Badge\5.jpg" /> <None Remove="Resources\Img\Badge\5.jpg" />
<None Remove="Resources\Img\Badge\logo.png" /> <None Remove="Resources\Img\Badge\logo.png" />
@ -90,10 +92,10 @@
<Resource Include="Resources\Img\Badge\2.jpg"> <Resource Include="Resources\Img\Badge\2.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource> </Resource>
<Resource Include="Resources\Img\Badge\3.png"> <Resource Include="Resources\Img\Badge\3.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource> </Resource>
<Resource Include="Resources\Img\Badge\4.png"> <Resource Include="Resources\Img\Badge\4.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource> </Resource>
<Resource Include="Resources\Img\Badge\5.jpg"> <Resource Include="Resources\Img\Badge\5.jpg">