Skip to content

Commit

Permalink
Add overlay to ImageCropper
Browse files Browse the repository at this point in the history
  • Loading branch information
shatyuka committed Mar 7, 2024
1 parent 7c3a552 commit 7523277
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 2 deletions.
5 changes: 5 additions & 0 deletions components/ImageCropper/src/ImageCropper.Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public partial class ImageCropper
/// </summary>
private const string MaskAreaPathPartName = "PART_MaskAreaPath";

/// <summary>
/// Key of the overlay layer.
/// </summary>
private const string OverlayAreaPathPartName = "PART_OverlayAreaPath";

/// <summary>
/// Key of the ImageCropperThumb that on the top.
/// </summary>
Expand Down
26 changes: 24 additions & 2 deletions components/ImageCropper/src/ImageCropper.Logic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,14 +448,20 @@ private void UpdateCropShape()
{
case CropShape.Rectangular:
_innerGeometry = new RectangleGeometry();
_overlayGeometry = new RectangleGeometry();
break;
case CropShape.Circular:
_innerGeometry = new EllipseGeometry();
_overlayGeometry = new EllipseGeometry();
break;
}

_maskAreaGeometryGroup.Children.Add(_outerGeometry);
_maskAreaGeometryGroup.Children.Add(_innerGeometry);
if (_overlayAreaPath != null)
{
_overlayAreaPath.Data = _overlayGeometry;
}
}

/// <summary>
Expand All @@ -473,7 +479,7 @@ private void UpdateMaskArea(bool animate = false)
switch (CropShape)
{
case CropShape.Rectangular:
if (_innerGeometry is RectangleGeometry rectangleGeometry)
var updateRectangleGeometry = (RectangleGeometry rectangleGeometry) =>
{
var to = new Point(_startX, _startY).ToRect(new Point(_endX, _endY));
if (animate)
Expand All @@ -486,11 +492,19 @@ private void UpdateMaskArea(bool animate = false)
{
rectangleGeometry.Rect = to;
}
};
if (_innerGeometry is RectangleGeometry innerRectangleGeometry)
{
updateRectangleGeometry(innerRectangleGeometry);
}
if (_overlayGeometry is RectangleGeometry overlayRectangleGeometry)
{
updateRectangleGeometry(overlayRectangleGeometry);
}

break;
case CropShape.Circular:
if (_innerGeometry is EllipseGeometry ellipseGeometry)
var updateEllipseGeometry = (EllipseGeometry ellipseGeometry) =>
{
var center = new Point(((_endX - _startX) / 2) + _startX, ((_endY - _startY) / 2) + _startY);
var radiusX = (_endX - _startX) / 2;
Expand All @@ -509,6 +523,14 @@ private void UpdateMaskArea(bool animate = false)
ellipseGeometry.RadiusX = radiusX;
ellipseGeometry.RadiusY = radiusY;
}
};
if (_innerGeometry is EllipseGeometry innerEllipseGeometry)
{
updateEllipseGeometry(innerEllipseGeometry);
}
if (_overlayGeometry is EllipseGeometry overlayEllipseGeometry)
{
updateEllipseGeometry(overlayEllipseGeometry);
}

break;
Expand Down
15 changes: 15 additions & 0 deletions components/ImageCropper/src/ImageCropper.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ public Brush Mask
set { SetValue(MaskProperty, value); }
}

/// <summary>
/// Gets or sets the overlay on the cropped image.
/// </summary>
public Brush Overlay
{
get { return (Brush)GetValue(OverlayProperty); }
set { SetValue(OverlayProperty, value); }
}

/// <summary>
/// Gets or sets a value for the style to use for the primary thumbs of the ImageCropper.
/// </summary>
Expand Down Expand Up @@ -175,6 +184,12 @@ public ThumbPlacement ThumbPlacement
public static readonly DependencyProperty MaskProperty =
DependencyProperty.Register(nameof(Mask), typeof(Brush), typeof(ImageCropper), new PropertyMetadata(default(Brush)));

/// <summary>
/// Identifies the <see cref="Overlay"/> dependency property.
/// </summary>
public static readonly DependencyProperty OverlayProperty =
DependencyProperty.Register(nameof(Overlay), typeof(Brush), typeof(ImageCropper), new PropertyMetadata(default(Brush)));

/// <summary>
/// Identifies the <see cref="PrimaryThumbStyle"/> dependency property.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions components/ImageCropper/src/ImageCropper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace CommunityToolkit.WinUI.Controls;
[TemplatePart(Name = ImageCanvasPartName, Type = typeof(Canvas))]
[TemplatePart(Name = SourceImagePartName, Type = typeof(Image))]
[TemplatePart(Name = MaskAreaPathPartName, Type = typeof(Path))]
[TemplatePart(Name = OverlayAreaPathPartName, Type = typeof(Path))]
[TemplatePart(Name = TopThumbPartName, Type = typeof(ImageCropperThumb))]
[TemplatePart(Name = BottomThumbPartName, Type = typeof(ImageCropperThumb))]
[TemplatePart(Name = LeftThumbPartName, Type = typeof(ImageCropperThumb))]
Expand All @@ -39,6 +40,7 @@ public partial class ImageCropper : Control
private Canvas? _imageCanvas;
private Image? _sourceImage;
private Path? _maskAreaPath;
private Path? _overlayAreaPath;
private ImageCropperThumb? _topThumb;
private ImageCropperThumb? _bottomThumb;
private ImageCropperThumb? _leftThumb;
Expand All @@ -59,6 +61,7 @@ public partial class ImageCropper : Control
private Rect _restrictedSelectRect = Rect.Empty;
private RectangleGeometry _outerGeometry;
private Geometry _innerGeometry;
private Geometry _overlayGeometry;
private TimeSpan _animationDuration = TimeSpan.FromSeconds(0.3);

/// <summary>
Expand Down Expand Up @@ -165,6 +168,7 @@ protected override void OnApplyTemplate()
_imageCanvas = GetTemplateChild(ImageCanvasPartName) as Canvas;
_sourceImage = GetTemplateChild(SourceImagePartName) as Image;
_maskAreaPath = GetTemplateChild(MaskAreaPathPartName) as Path;
_overlayAreaPath = GetTemplateChild(OverlayAreaPathPartName) as Path;
_topThumb = GetTemplateChild(TopThumbPartName) as ImageCropperThumb;
_bottomThumb = GetTemplateChild(BottomThumbPartName) as ImageCropperThumb;
_leftThumb = GetTemplateChild(LeftThumbPartName) as ImageCropperThumb;
Expand Down Expand Up @@ -195,6 +199,11 @@ private void HookUpEvents()
_maskAreaPath.Data = _maskAreaGeometryGroup;
}

if (_overlayAreaPath != null)
{
_overlayAreaPath.Data = _overlayGeometry;
}

if (_topThumb != null)
{
_topThumb.Position = ThumbPosition.Top;
Expand Down
3 changes: 3 additions & 0 deletions components/ImageCropper/src/ImageCropper.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
Source="{TemplateBinding Source}" />
<Path x:Name="PART_MaskAreaPath"
Fill="{TemplateBinding Mask}" />
<Path x:Name="PART_OverlayAreaPath"
Fill="{TemplateBinding Overlay}"
IsHitTestVisible="False" />
<controls:ImageCropperThumb x:Name="PART_TopThumb"
Style="{TemplateBinding SecondaryThumbStyle}" />
<!-- ui:FrameworkElementExtensions.Cursor="SizeNorthSouth" -->
Expand Down

0 comments on commit 7523277

Please sign in to comment.