Skip to content

Commit ef6f173

Browse files
committed
Add ImageFrame Sample
1 parent b4b6693 commit ef6f173

File tree

11 files changed

+279
-883
lines changed

11 files changed

+279
-883
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ Install-Package DevWinUI
131131
## 🔥 DevWinUI.Controls 🔥
132132
### ⚡ What’s Inside? ⚡
133133

134+
- ✨ ImageFrame
134135
- ✨ FrostedGlass
135136
- ✨ ProfileControl
136137
- ✨ FluidBanner
@@ -300,6 +301,9 @@ Install-Package DevWinUI.ContextMenu
300301

301302
## 🕰️ History 🕰️
302303

304+
### ImageFrame
305+
![ImageFrame](https://raw.githubusercontent.com/ghost1372/DevWinUI-Resources/refs/heads/main/DevWinUI-Docs/ImageFrame.gif)
306+
303307
### FrostedGlass
304308
![FrostedGlass](https://raw.githubusercontent.com/ghost1372/DevWinUI-Resources/refs/heads/main/DevWinUI-Docs/FrostedGlass.gif)
305309

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace DevWinUI;
2+
3+
internal static partial class ColorHelperEx
4+
{
5+
public static async Task<Color> GetImageEdgeColorWithWin2DAsync(CanvasDevice device, Uri path)
6+
{
7+
using var bitmap = await CanvasBitmap.LoadAsync(device, path);
8+
var colors = bitmap.GetPixelColors();
9+
10+
uint width = bitmap.SizeInPixels.Width;
11+
uint height = bitmap.SizeInPixels.Height;
12+
13+
var edgePixels = new List<Color>();
14+
15+
for (int x = 0; x < width; x++)
16+
{
17+
edgePixels.Add(colors[x]); // top
18+
edgePixels.Add(colors[(height - 1) * width + x]); // bottom
19+
}
20+
for (int y = 0; y < height; y++)
21+
{
22+
edgePixels.Add(colors[y * width]); // left
23+
edgePixels.Add(colors[y * width + (width - 1)]); // right
24+
}
25+
26+
byte r = (byte)edgePixels.Average(c => c.R);
27+
byte g = (byte)edgePixels.Average(c => c.G);
28+
byte b = (byte)edgePixels.Average(c => c.B);
29+
30+
return Color.FromArgb(255, r, g, b);
31+
}
32+
}

dev/DevWinUI.Controls/CompositionProToolkit/Expressions/README.md

Lines changed: 0 additions & 841 deletions
This file was deleted.

dev/DevWinUI.Controls/Controls/Composition/CompositionShadow/CompositionShadow.cs

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -136,34 +136,6 @@ private void UpdateShadowSize()
136136
_shadowVisual.Size = newSize;
137137
}
138138

139-
private async Task<Color> GetImageEdgeColorWithWin2DAsync(CanvasDevice device, Uri path)
140-
{
141-
using var bitmap = await CanvasBitmap.LoadAsync(device, path);
142-
var colors = bitmap.GetPixelColors();
143-
144-
uint width = bitmap.SizeInPixels.Width;
145-
uint height = bitmap.SizeInPixels.Height;
146-
147-
var edgePixels = new List<Color>();
148-
149-
for (int x = 0; x < width; x++)
150-
{
151-
edgePixels.Add(colors[x]); // top
152-
edgePixels.Add(colors[(height - 1) * width + x]); // bottom
153-
}
154-
for (int y = 0; y < height; y++)
155-
{
156-
edgePixels.Add(colors[y * width]); // left
157-
edgePixels.Add(colors[y * width + (width - 1)]); // right
158-
}
159-
160-
byte r = (byte)edgePixels.Average(c => c.R);
161-
byte g = (byte)edgePixels.Average(c => c.G);
162-
byte b = (byte)edgePixels.Average(c => c.B);
163-
164-
return Color.FromArgb(255, r, g, b);
165-
}
166-
167139
private async Task UpdateColorFromImageAsync()
168140
{
169141
if (!UseEdgeColorFromImage || ImageSourceForEdgeColor == null)
@@ -188,7 +160,7 @@ private async Task UpdateColorFromImageAsync()
188160
if (uri != null)
189161
{
190162
var device = CanvasDevice.GetSharedDevice();
191-
var color = await GetImageEdgeColorWithWin2DAsync(device, uri);
163+
var color = await ColorHelperEx.GetImageEdgeColorWithWin2DAsync(device, uri);
192164
Color = color;
193165
}
194166
else

dev/DevWinUI.Controls/Controls/Composition/ImageFrame/ImageFrame.cs

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
[TemplatePart(Name = RenderBorder, Type = typeof(Border))]
77
public sealed partial class ImageFrame : Control, IDisposable
88
{
9+
private Color _shadowColor = Colors.Transparent;
10+
911
#region Enums
1012

1113
private enum ImageEngineState
@@ -81,6 +83,43 @@ private enum ImageEngineState
8183

8284
#region Dependency Properties
8385

86+
public bool UseAutoShadowColor
87+
{
88+
get { return (bool)GetValue(UseAutoShadowColorProperty); }
89+
set { SetValue(UseAutoShadowColorProperty, value); }
90+
}
91+
92+
public static readonly DependencyProperty UseAutoShadowColorProperty =
93+
DependencyProperty.Register(nameof(UseAutoShadowColor), typeof(bool), typeof(ImageFrame), new PropertyMetadata(false, OnUseAutoShadowColor));
94+
95+
private async static void OnUseAutoShadowColor(DependencyObject d, DependencyPropertyChangedEventArgs e)
96+
{
97+
var ctl = (ImageFrame)d;
98+
if (ctl != null && ctl.DisplayShadow)
99+
{
100+
ctl.UpdateShadowColor();
101+
ctl.InvalidateArrange();
102+
}
103+
}
104+
105+
private async void UpdateShadowColor()
106+
{
107+
if (UseAutoShadowColor)
108+
{
109+
var uri = GetUriFromSource();
110+
if (uri != null)
111+
{
112+
var device = CanvasDevice.GetSharedDevice();
113+
_shadowColor = await ColorHelperEx.GetImageEdgeColorWithWin2DAsync(device, uri);
114+
}
115+
}
116+
else
117+
{
118+
_shadowColor = ShadowColor;
119+
}
120+
}
121+
122+
84123
#region AlignX
85124

86125
/// <summary>
@@ -570,6 +609,7 @@ private void OnShadowColorChanged()
570609
// Refresh Layout if shadow is displayed
571610
if (DisplayShadow)
572611
{
612+
UpdateShadowColor();
573613
InvalidateArrange();
574614
}
575615
}
@@ -807,6 +847,8 @@ private void OnSourceChanged()
807847

808848
// If the ImageFrame is properly initialized, then we can schedule this Uri
809849
// to be loaded next.
850+
851+
UpdateShadowColor();
810852
ScheduleNextLoad();
811853
}
812854

@@ -914,17 +956,17 @@ private void OnTransitionDurationChanged(TimeSpan newTransitionDuration)
914956
/// TransitionMode Dependency Property
915957
/// </summary>
916958
public static readonly DependencyProperty TransitionModeProperty =
917-
DependencyProperty.Register(nameof(TransitionMode), typeof(TransitionModeType), typeof(ImageFrame),
918-
new PropertyMetadata(TransitionModeType.FadeIn));
959+
DependencyProperty.Register(nameof(TransitionMode), typeof(ImageFrameTransitionMode), typeof(ImageFrame),
960+
new PropertyMetadata(ImageFrameTransitionMode.FadeIn));
919961

920962
/// <summary>
921963
/// Gets or sets the TransitionMode property. This dependency property
922964
/// indicates the type of transition animation to employ for displaying
923965
/// an image after it has been loaded.
924966
/// </summary>
925-
public TransitionModeType TransitionMode
967+
public ImageFrameTransitionMode TransitionMode
926968
{
927-
get => (TransitionModeType)GetValue(TransitionModeProperty);
969+
get => (ImageFrameTransitionMode)GetValue(TransitionModeProperty);
928970
set => SetValue(TransitionModeProperty, value);
929971
}
930972

@@ -1235,7 +1277,7 @@ protected override Size ArrangeOverride(Size finalSize)
12351277
: (_shadow ?? (_shadow = _compositor.CreateDropShadow()));
12361278

12371279
shadow.BlurRadius = ShadowBlurRadius.ToSingle();
1238-
shadow.Color = ShadowColor;
1280+
shadow.Color = _shadowColor;
12391281
shadow.Offset = new Vector3(ShadowOffsetX.ToSingle(), ShadowOffsetY.ToSingle(), 0);
12401282
shadow.Opacity = ShadowOpacity.ToSingle();
12411283
shadow.Mask = _layerEffectBrush.GetSourceParameter("mask");
@@ -1833,35 +1875,35 @@ private void StartTransition(bool isFirstLoad)
18331875
switch (TransitionMode)
18341876
{
18351877
// New content fades into view
1836-
case TransitionModeType.FadeIn:
1878+
case ImageFrameTransitionMode.FadeIn:
18371879
nextContent.StartAnimation("Opacity", _fadeInAnimation);
18381880
break;
18391881
// New content slides from right to left
1840-
case TransitionModeType.SlideLeft:
1882+
case ImageFrameTransitionMode.SlideLeft:
18411883
nextContent.Offset = new Vector3(nextContent.Size.X, 0, 0);
18421884
nextContent.Opacity = 1;
18431885
nextContent.StartAnimation("Offset", _offsetAnimation);
18441886
break;
18451887
// New content slides from left to right
1846-
case TransitionModeType.SlideRight:
1888+
case ImageFrameTransitionMode.SlideRight:
18471889
nextContent.Offset = new Vector3(-nextContent.Size.X, 0, 0);
18481890
nextContent.Opacity = 1;
18491891
nextContent.StartAnimation("Offset", _offsetAnimation);
18501892
break;
18511893
// New content slides up from bottom to top
1852-
case TransitionModeType.SlideUp:
1894+
case ImageFrameTransitionMode.SlideUp:
18531895
nextContent.Offset = new Vector3(0, nextContent.Size.Y, 0);
18541896
nextContent.Opacity = 1;
18551897
nextContent.StartAnimation("Offset", _offsetAnimation);
18561898
break;
18571899
// New content slides down from top to bottom
1858-
case TransitionModeType.SlideDown:
1900+
case ImageFrameTransitionMode.SlideDown:
18591901
nextContent.Offset = new Vector3(0, -nextContent.Size.Y, 0);
18601902
nextContent.Opacity = 1;
18611903
nextContent.StartAnimation("Offset", _offsetAnimation);
18621904
break;
18631905
// New content zooms into view
1864-
case TransitionModeType.ZoomIn:
1906+
case ImageFrameTransitionMode.ZoomIn:
18651907
nextContent.Scale = new Vector3(MinScaleFactor, MinScaleFactor, 1);
18661908
nextContent.Offset = new Vector3(nextContent.Size.X * (1 - MinScaleFactor) / 2f,
18671909
nextContent.Size.Y * (1 - MinScaleFactor) / 2f, 0);
@@ -1890,7 +1932,7 @@ private void DisplayPlaceHolder()
18901932
{
18911933
_placeholderBackgroundVisual.Opacity = 1;
18921934
}
1893-
else if (TransitionMode == TransitionModeType.FadeIn)
1935+
else if (TransitionMode == ImageFrameTransitionMode.FadeIn)
18941936
{
18951937
_placeholderBackgroundVisual.StartAnimation("Opacity", _fadeInAnimation);
18961938
}

dev/DevWinUI.Controls/Controls/Composition/ImageFrame/TransitionModeType.cs renamed to dev/DevWinUI.Controls/Controls/Composition/ImageFrame/ImageFrameTransitionMode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/// This enum defines the various types of transitions that can
55
/// be used to display the loaded image in the ImageFrame
66
/// </summary>
7-
public enum TransitionModeType
7+
public enum ImageFrameTransitionMode
88
{
99
/// <summary>
1010
/// The loaded image fades into view.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Microsoft.UI.Xaml.Data;
2+
3+
namespace DevWinUIGallery.Common;
4+
5+
internal partial class DoubleToCornerRadiusConverter : IValueConverter
6+
{
7+
public object Convert(object value, Type targetType, object parameter, string language)
8+
{
9+
if (value is double vDouble)
10+
{
11+
return new CornerRadius(vDouble);
12+
}
13+
14+
return value;
15+
}
16+
17+
public object ConvertBack(object value, Type targetType, object parameter, string language)
18+
{
19+
throw new NotImplementedException();
20+
}
21+
}

dev/DevWinUI.Gallery/Themes/Converters.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
xmlns:local="using:DevWinUIGallery.Common">
44

55
<local:DoubleToThicknessConverter x:Key="DoubleToThicknessConverter" />
6+
<local:DoubleToCornerRadiusConverter x:Key="DoubleToCornerRadiusConverter" />
67
</ResourceDictionary>

dev/DevWinUI.Gallery/ViewModels/BaseViewModel.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ public partial class BaseViewModel : ObservableObject
1010
[ObservableProperty]
1111
public partial DigitalSegmentOption DigitalSegmentSelectedModel { get; set; }
1212

13+
[ObservableProperty]
14+
public partial ObservableCollection<ImageFrameTransitionMode> ImageFrameTransition { get; set; } = new ObservableCollection<ImageFrameTransitionMode>(Enum.GetValues<ImageFrameTransitionMode>());
15+
16+
[ObservableProperty]
17+
public partial ObservableCollection<AlignmentX> ImageFrameAlignmentX { get; set; } = new ObservableCollection<AlignmentX>(Enum.GetValues<AlignmentX>());
18+
19+
[ObservableProperty]
20+
public partial ObservableCollection<AlignmentY> ImageFrameAlignmentY { get; set; } = new ObservableCollection<AlignmentY>(Enum.GetValues<AlignmentY>());
21+
1322
[ObservableProperty]
1423
public partial ObservableCollection<MenuFlyoutSecondaryMenuPlacement> SecondaryMenuPlacement { get; set; } = new ObservableCollection<MenuFlyoutSecondaryMenuPlacement>(Enum.GetValues<MenuFlyoutSecondaryMenuPlacement>());
1524

0 commit comments

Comments
 (0)