2026-03-27 17:42:25 +08:00

201 lines
11 KiB
XML

<UserControl x:Class="Wpf_AiSportsMicrospace.MyUserControl.CoverFlowControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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"
d:DesignHeight="900"
d:DesignWidth="1920">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<local:ProgressToRectangleGeometryConverter x:Key="ProgressToRectangleGeometryConverter"/>
<local:SelectedAndProgressToVisibilityConverter x:Key="SelectedAndProgressToVisibilityConverter"/>
<!-- 单张卡片模板:中间卡片(选中)发光 + 进度条 -->
<DataTemplate x:Key="CardTemplate" DataType="{x:Type local:CoverFlowItem}">
<ContentControl x:Name="ImageContainer"
Width="368"
Height="534"
Background="Transparent"
BorderThickness="2"
BorderBrush="#00FFFFFF"
SnapsToDevicePixels="True">
<!-- 用 ContentControl.Template 承载 Border + 呼吸灯 Trigger -->
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border x:Name="Root"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
CornerRadius="24"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ContentControl.Style>
<Grid ClipToBounds="False">
<Image Source="{Binding ImageUri}"
Stretch="Uniform"
Width="308"
Height="514"/>
<!-- 进度条底轨 -->
<Path Stroke="#2A1B1B1B"
StrokeThickness="10"
Width="336"
Height="500"
HorizontalAlignment="Center"
VerticalAlignment="Center"
StrokeStartLineCap="Round"
StrokeEndLineCap="Round"
Data="{Binding Path=Progress, Converter={StaticResource ProgressToRectangleGeometryConverter}, ConverterParameter='336,500,18,7'}">
<Path.Visibility>
<MultiBinding Converter="{StaticResource SelectedAndProgressToVisibilityConverter}">
<Binding Path="IsSelected"/>
<Binding Path="Progress"/>
</MultiBinding>
</Path.Visibility>
</Path>
<!-- 进度条前景 -->
<Path StrokeThickness="7"
Width="336"
Height="500"
HorizontalAlignment="Center"
VerticalAlignment="Center"
StrokeStartLineCap="Round"
StrokeEndLineCap="Round"
Data="{Binding Progress, Converter={StaticResource ProgressToRectangleGeometryConverter}, ConverterParameter='336,500,18,7'}">
<Path.Visibility>
<MultiBinding Converter="{StaticResource SelectedAndProgressToVisibilityConverter}">
<Binding Path="IsSelected"/>
<Binding Path="Progress"/>
</MultiBinding>
</Path.Visibility>
<Path.Effect>
<DropShadowEffect Color="{Binding ProgressColor1}" BlurRadius="10" ShadowDepth="0" Opacity="0.75"/>
</Path.Effect>
<Path.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="{Binding ProgressColor1}"/>
<GradientStop Offset="0.5" Color="{Binding ProgressColor2}"/>
<GradientStop Offset="1" Color="{Binding ProgressColor1}"/>
</LinearGradientBrush>
</Path.Stroke>
<Path.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Opacity)"
From="0.45" To="0.72" Duration="0:0:0.9"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Grid>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
<Grid Background="Transparent" ClipToBounds="False">
<!-- 轮播视口(显示 4 张),卡片发光允许溢出所以外层不裁剪 -->
<Canvas x:Name="CarouselCanvas"
Width="1474"
Height="580"
Background="Transparent"
Focusable="True"
PreviewKeyDown="Carousel_PreviewKeyDown"
PreviewMouseWheel="Carousel_PreviewMouseWheel">
<!-- 左二/左一/中/右一四张 -->
<ContentPresenter x:Name="CardFarLeft"
ContentTemplate="{StaticResource CardTemplate}"
MouseLeftButtonUp="CardFarLeft_Click"/>
<ContentPresenter x:Name="CardLeft"
ContentTemplate="{StaticResource CardTemplate}"
MouseLeftButtonUp="CardLeft_Click"/>
<ContentPresenter x:Name="CardCenter"
ContentTemplate="{StaticResource CardTemplate}"
MouseLeftButtonUp="CardCenter_Click"/>
<ContentPresenter x:Name="CardRight"
ContentTemplate="{StaticResource CardTemplate}"
MouseLeftButtonUp="CardRight_Click"/>
<!-- 预备卡片:用于从右/左滑入 -->
<ContentPresenter x:Name="CardSpare"
ContentTemplate="{StaticResource CardTemplate}"
Opacity="0"/>
<!-- 固定选中态:始终锁定中间槽位,不随卡片移动 -->
<Border x:Name="FixedSelectedRing"
Width="368"
Height="534"
CornerRadius="26"
Background="Transparent"
RenderTransformOrigin="0.5,0.5"
IsHitTestVisible="False"
Canvas.Left="796"
Canvas.Top="0">
<Border.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</Border.RenderTransform>
<Grid ClipToBounds="False">
<!-- 外层金色主框 -->
<Border x:Name="SelectedOuterRing"
CornerRadius="26"
BorderThickness="6"
Background="Transparent">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0" Color="#FFFFF1A3"/>
<GradientStop Offset="0.45" Color="#FFFFD84A"/>
<GradientStop Offset="1" Color="#FFFABF24"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Effect>
<DropShadowEffect Color="#FFFFD84A" BlurRadius="36" ShadowDepth="0" Opacity="0.78"/>
</Border.Effect>
</Border>
<!-- 内层高光细框 -->
<Border x:Name="SelectedInnerRing"
Margin="12"
CornerRadius="20"
BorderThickness="2.6"
Background="Transparent"
BorderBrush="#CCFFF8D6"
Opacity="0.9"/>
</Grid>
<Border.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
From="1.0" To="1.04" Duration="0:0:1.35" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
From="1.0" To="1.04" Duration="0:0:1.35" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="SelectedOuterRing"
Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Opacity)"
From="0.58" To="0.92" Duration="0:0:1.35" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="SelectedInnerRing"
Storyboard.TargetProperty="Opacity"
From="0.72" To="1.0" Duration="0:0:1.35" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
</Canvas>
</Grid>
</UserControl>