網站首頁 編程語言 正文
實現思路
制作一個用戶頭像選擇器仿?WeGame
制作一個用戶頭像選擇Canvas
為父控件所實現,展示圖片使用Image
,Path
當作上方的蒙版;
Canvas
:主要用途方便移動Image
,設置ClipToBounds="True"
裁剪為一個正方形200x200
做為主要展示區域;
Image
:展示需要裁剪的圖片;
Path
:CombinedGeometry[1]繪制蒙版大小200x200
效果如下;
當選擇一個本地圖片的時候判斷寬與高誰更大,誰小就將它更改為200
?,另一邊做等比縮放后給到DrawingVisual
繪制一個新的BitmapFrame[2]給Image
控件做展示;
當移動圖片的時候右側展示當前區域使用CroppedBitmap[3]進行裁剪并顯示;
源碼Github[4]?Gitee[5]
核心代碼
1)CropAvatar.xaml
?代碼如下;
<ResourceDictionary?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ????????????????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ????????????????????xmlns:controls="clr-namespace:WPFDevelopers.Controls"> ????<ResourceDictionary.MergedDictionaries> ????????<ResourceDictionary?Source="Basic/ControlBasic.xaml"/> ????</ResourceDictionary.MergedDictionaries> ????<Style?TargetType="controls:CropAvatar"?BasedOn="{StaticResource?ControlBasicStyle}"> ????????<Setter?Property="Template"> ????????????<Setter.Value> ????????????????<ControlTemplate?TargetType="{x:Type?controls:CropAvatar}"> ????????????????????<Canvas?x:Name="PART_Canvas"?ClipToBounds="True"> ????????????????????????<Image?x:Name="PART_Image"?Cursor="SizeAll"?></Image> ????????????????????????<Path?x:Name="PART_Layout"? ??????????????????????????????Fill="{DynamicResource?BlackSolidColorBrush}"? ??????????????????????????????Width="200"?Height="200"? ??????????????????????????????Opacity=".5"> ????????????????????????????<Path.Data> ????????????????????????????????<CombinedGeometry?GeometryCombineMode="Xor"> ????????????????????????????????????<CombinedGeometry.Geometry1> ????????????????????????????????????????<RectangleGeometry?Rect="0,0,200,200"/> ????????????????????????????????????</CombinedGeometry.Geometry1> ????????????????????????????????????<CombinedGeometry.Geometry2> ????????????????????????????????????????<EllipseGeometry?Center="100,100"?RadiusX="100"?RadiusY="100"/> ????????????????????????????????????</CombinedGeometry.Geometry2> ????????????????????????????????</CombinedGeometry> ????????????????????????????</Path.Data> ????????????????????????</Path> ????????????????????????<Grid?x:Name="PART_Grid"?Width="200"?Height="200"> ????????????????????????????<Button?x:Name="PART_ReplaceButton"?Style="{StaticResource?PathButton}" ????????????????????????????????????HorizontalAlignment="Right" ????????????????????????????????????VerticalAlignment="Top" ????????????????????????????????????Width="40"?Height="40"?ToolTip="更換圖片" ????????????????????????????????????Visibility="Collapsed"> ????????????????????????????????<Button.Content> ????????????????????????????????????<Path?Data="{StaticResource?PathReplace}" ??????????????????????????????????????????Fill="{StaticResource?PrimaryNormalSolidColorBrush}" ??????????????????????????????????????????Height="15" ??????????????????????????????????????????Width="15" ??????????????????????????????????????????Stretch="Fill"?/> ????????????????????????????????</Button.Content> ????????????????????????????</Button> ????????????????????????????<Button?x:Name="PART_AddButton"?Style="{StaticResource?PathButton}" ????????????????????????????????????Width="40"?Height="40"?ToolTip="選擇圖片"> ????????????????????????????????<Button.Content> ????????????????????????????????????<Path?Data="{StaticResource?PathAdd}" ??????????????????????????????????????????Fill="{StaticResource?PrimaryNormalSolidColorBrush}" ??????????????????????????????????????????Height="20" ??????????????????????????????????????????Width="20" ??????????????????????????????????????????Stretch="Fill"? ??????????????????????????????????????????RenderTransformOrigin="0.5,0.5"?IsHitTestVisible="False"> ????????????????????????????????????????<Path.RenderTransform> ????????????????????????????????????????????<RotateTransform?Angle="45"/> ????????????????????????????????????????</Path.RenderTransform> ????????????????????????????????????</Path> ????????????????????????????????</Button.Content> ????????????????????????????</Button> ????????????????????????</Grid> ????????????????????</Canvas> ????????????????</ControlTemplate> ????????????</Setter.Value> ????????</Setter> ????</Style> </ResourceDictionary>
2)CropAvatar.cs
?代碼如下;
using?System; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Input; using?System.Windows.Media; using?System.Windows.Media.Imaging; using?System.Windows.Shapes; using?WPFDevelopers.Helpers; namespace?WPFDevelopers.Controls { ????[TemplatePart(Name?=?CanvasTemplateName,?Type?=?typeof(Canvas))] ????[TemplatePart(Name?=?ImageTemplateName,?Type?=?typeof(Image))] ????[TemplatePart(Name?=?PathTemplateName,?Type?=?typeof(Path))] ????[TemplatePart(Name?=?GridTemplateName,?Type?=?typeof(Grid))] ????[TemplatePart(Name?=?ReplaceButtonTemplateName,?Type?=?typeof(Button))] ????[TemplatePart(Name?=?AddButtonTemplateName,?Type?=?typeof(Button))] ????public?partial?class?CropAvatar?:?Control ????{ ????????private?const?string?CanvasTemplateName?=?"PART_Canvas"; ????????private?const?string?ImageTemplateName?=?"PART_Image"; ????????private?const?string?PathTemplateName?=?"PART_Layout"; ????????private?const?string?GridTemplateName?=?"PART_Grid"; ????????private?const?string?ReplaceButtonTemplateName?=?"PART_ReplaceButton"; ????????private?const?string?AddButtonTemplateName?=?"PART_AddButton"; ????????private?Point?point; ????????private?const?int?_size?=?200; ????????private?bool?isDown; ????????private?bool?isLeft; ????????private?CroppedBitmap?crop; ????????private?Canvas?canvas; ????????private?Image?image; ????????private?Path?path; ????????private?Grid?grid; ????????private?Button?replaceButton,?addButton; ????????private?int?initialX,?initialY,?voffsetX,?voffsetY; ????????private?double?vNewStartX,?vNewStartY,?_StartX,?_StartY,?centerX,?centerY; ????????private?BitmapFrame?bitmapFrame; ????????public?ImageSource?OutImageSource ????????{ ????????????get?{?return?(ImageSource)GetValue(OutImageSourceProperty);?} ????????????set?{?SetValue(OutImageSourceProperty,?value);?} ????????} ????????public?static?readonly?DependencyProperty?OutImageSourceProperty?= ????????????DependencyProperty.Register("OutImageSource",?typeof(ImageSource),?typeof(CropAvatar),?new?PropertyMetadata(null)); ????????static?CropAvatar() ????????{ ????????????DefaultStyleKeyProperty.OverrideMetadata(typeof(CropAvatar),?new?FrameworkPropertyMetadata(typeof(CropAvatar))); ????????} ????????public?override?void?OnApplyTemplate() ????????{ ????????????base.OnApplyTemplate(); ????????????canvas?=?GetTemplateChild(CanvasTemplateName)?as?Canvas; ????????????canvas.Loaded?+=?Canvas_Loaded; ????????????grid?=?GetTemplateChild(GridTemplateName)?as?Grid; ????????????image?=?GetTemplateChild(ImageTemplateName)?as?Image; ????????????image.MouseDown?+=?Image_MouseDown; ????????????image.MouseMove?+=?Image_MouseMove; ????????????image.MouseUp?+=?Image_MouseUp; ????????????image.MouseLeave?+=?Image_MouseLeave; ????????????path?=?GetTemplateChild(PathTemplateName)?as?Path; ????????????replaceButton?=?GetTemplateChild(ReplaceButtonTemplateName)?as?Button; ????????????replaceButton.Click?+=?ReplaceButton_Click; ????????????addButton?=?GetTemplateChild(AddButtonTemplateName)?as?Button; ????????????addButton.Click?+=?AddButton_Click; ????????} ????????private?void?Canvas_Loaded(object?sender,?RoutedEventArgs?e) ????????{ ????????????if?(sender?is?Canvas?canvas) ????????????{ ????????????????var?width?=?canvas.ActualWidth; ????????????????var?height?=?canvas.ActualHeight; ????????????????centerX?=?(width?-?path.Width)?/?2.0d; ????????????????centerY?=?(height?-?path.Height)?/?2.0d; ????????????????canvas.Clip?=?new?RectangleGeometry(new?Rect(centerX,?centerY,?200,?200));? ????????????????Canvas.SetLeft(path,?centerX); ????????????????Canvas.SetTop(path,?centerY); ????????????????Canvas.SetLeft(grid,?centerX); ????????????????Canvas.SetTop(grid,?centerY); ????????????} ????????} ????????private?void?Image_MouseLeave(object?sender,?MouseEventArgs?e) ????????{ ????????????isDown?=?false; ????????????if?(isLeft) ????????????????_StartX?=?Canvas.GetLeft(image); ????????????else ????????????????_StartY?=?Canvas.GetTop(image); ????????} ????????private?void?Image_MouseUp(object?sender,?MouseButtonEventArgs?e) ????????{ ????????????if?(isDown) ????????????{ ????????????????var?vPoint?=?e.GetPosition(this); ????????????????if?(isLeft) ????????????????{ ????????????????????_StartX?=?Canvas.GetLeft(image); ????????????????????initialX?=?voffsetX; ????????????????} ????????????????else ????????????????{ ????????????????????_StartY?=?Canvas.GetTop(image); ????????????????????initialY?=?voffsetY; ????????????????} ????????????} ????????} ????????private?void?Image_MouseMove(object?sender,?MouseEventArgs?e) ????????{ ????????????if?(e.LeftButton?==?MouseButtonState.Pressed?&&?isDown) ????????????{ ????????????????var?vPoint?=?e.GetPosition(this); ????????????????if?(isLeft) ????????????????{ ????????????????????var?voffset?=?vPoint.X?-?point.X; ????????????????????vNewStartX?=?_StartX?+?voffset; ????????????????????var?xPath?=?Canvas.GetLeft(path); ????????????????????if?(vNewStartX?<=?xPath?&&?vNewStartX?>=?-(bitmapFrame.Width?-?200?-?xPath)) ????????????????????{ ????????????????????????Canvas.SetLeft(image,?vNewStartX); ????????????????????????voffsetX?=?initialX?-?(int)voffset; ????????????????????????voffsetX?=?voffsetX?<?0???0?:?voffsetX; ????????????????????????crop?=?new?CroppedBitmap(bitmapFrame,?new?Int32Rect(voffsetX,?0,?_size,?_size)); ????????????????????} ????????????????} ????????????????else ????????????????{ ????????????????????var?voffset?=?vPoint.Y?-?point.Y; ????????????????????vNewStartY?=?_StartY?+?voffset; ????????????????????var?yPath?=?Canvas.GetTop(path); ????????????????????if?(vNewStartY?<=?yPath?&&?vNewStartY?>=?-(bitmapFrame.Height?-?200?-?yPath)) ????????????????????{ ????????????????????????Canvas.SetTop(image,?vNewStartY); ????????????????????????voffsetY?=?initialY?-?(int)voffset; ????????????????????????voffsetY?=?voffsetY?<?0???0?:?voffsetY; ????????????????????????crop?=?new?CroppedBitmap(bitmapFrame,?new?Int32Rect(0,?voffsetY,?_size,?_size)); ????????????????????} ????????????????} ????????????????OutImageSource?=?crop; ????????????} ????????} ????????private?void?Image_MouseDown(object?sender,?MouseButtonEventArgs?e) ????????{ ????????????isDown?=?true; ????????????point?=?e.GetPosition(this); ????????} ????????private?void?ReplaceButton_Click(object?sender,?RoutedEventArgs?e) ????????{ ????????????InitialImage(); ????????} ????????private?void?AddButton_Click(object?sender,?RoutedEventArgs?e) ????????{ ????????????InitialImage(); ????????} ????????void?InitialImage() ????????{ ????????????vNewStartX?=?0; ????????????vNewStartY?=?0; ????????????var?uri?=?ControlsHelper.ImageUri(); ????????????if?(uri?==?null)?return; ????????????var?bitmap?=?new?BitmapImage(uri); ????????????if?(bitmap.Height?>?bitmap.Width) ????????????{ ????????????????double?scale?=?(double)bitmap.Width?/?(double)path.Width; ????????????????image.Width?=?_size; ????????????????image.Height?=?(double)bitmap.Height?/?scale; ????????????????isLeft?=?false; ????????????} ????????????else?if?(bitmap.Width?>?bitmap.Height) ????????????{ ????????????????double?scale?=?(double)bitmap.Height?/?(double)path.Height; ????????????????image.Width?=?(double)bitmap.Width?/?scale; ????????????????image.Height?=?_size; ????????????????isLeft?=?true; ????????????} ????????????bitmapFrame?=?ControlsHelper.CreateResizedImage(bitmap,?(int)image.Width,?(int)image.Height,?0); ????????????image.Source?=?bitmapFrame; ????????????if?(image.Source?!=?null) ????????????{ ????????????????replaceButton.Visibility?=?Visibility.Visible; ????????????????addButton.Visibility?=?Visibility.Collapsed; ????????????} ????????????Canvas.SetLeft(grid,?centerX); ????????????Canvas.SetTop(grid,?centerY); ????????????_StartX?=?(canvas.ActualWidth?-?image.Width)?/?2.0d; ????????????_StartY?=?(canvas.ActualHeight?-?image.Height)?/?2.0d; ????????????Canvas.SetLeft(image,?_StartX); ????????????Canvas.SetTop(image,?_StartY);???????? ????????????if?(isLeft) ????????????{ ????????????????initialX?=?(int)(image.Width?-?200)?/?2; ????????????????initialY?=?0; ????????????????crop?=?new?CroppedBitmap(bitmapFrame,?new?Int32Rect(initialX,?0,?_size,?_size)); ????????????} ????????????else ????????????{ ????????????????initialY?=?(int)(image.Height?-?200)?/?2; ????????????????initialX?=?0; ????????????????crop?=?new?CroppedBitmap(bitmapFrame,?new?Int32Rect(0,?initialY,?_size,?_size)); ????????????} ????????????OutImageSource?=?crop; ????????} ??????? ????} }
3)CropAvatarWindow.xaml
使用如下;
<ws:Window?x:Class="WPFDevelopers.Samples.ExampleViews.CropAvatarWindow" ????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ????????xmlns:d="http://schemas.microsoft.com/expression/blend/2008" ????????xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" ????????xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" ????????xmlns:ws="https://github.com/WPFDevelopersOrg.WPFDevelopers.Minimal" ????????mc:Ignorable="d"??WindowStyle="ToolWindow"?ResizeMode="NoResize" ????????WindowStartupLocation="CenterScreen" ????????Title="WPF?開發者-頭像選擇器"?Height="450"?Width="800"> ????<Grid> ????????<Grid.ColumnDefinitions> ????????????<ColumnDefinition/> ????????????<ColumnDefinition/> ????????</Grid.ColumnDefinitions> ????????<Grid.RowDefinitions> ????????????<RowDefinition/> ????????????<RowDefinition?Height="Auto"/> ????????</Grid.RowDefinitions> ????????<wpfdev:CropAvatar?x:Name="MyCropAvatar"/> ????????<Image?Grid.Column="1"?Name="CropAvatarImage"?Source="{Binding?ElementName=MyCropAvatar,Path=OutImageSource}"? ???????????????Stretch="Fill"?Width="200"?Height="200"> ????????????<Image.Clip> ????????????????<EllipseGeometry?Center="100,100"?RadiusX="100"?RadiusY="100"/> ????????????</Image.Clip> ????????</Image> ????????<UniformGrid?Grid.Row="1"?Grid.ColumnSpan="2"? ?????????????????????HorizontalAlignment="Center"? ?????????????????????VerticalAlignment="Center"> ????????????<Button??Content="保存"?Click="btnSave_Click"?Style="{StaticResource?PrimaryButton}"?Margin="4,0"/> ????????????<Button??Content="關閉"?Click="btnClose_Click"?Margin="4,0"/> ????????</UniformGrid> ????</Grid> </ws:Window>
4)?CropAvatarWindow.xaml.cs
?代碼如下;
using?System.Windows; namespace?WPFDevelopers.Samples.ExampleViews { ????///?<summary> ????///?CropAvatarWindow.xaml?的交互邏輯 ????///?</summary> ????public?partial?class?CropAvatarWindow? ????{ ????????public?CropAvatarWindow() ????????{ ????????????InitializeComponent(); ????????} ????????private?void?btnSave_Click(object?sender,?RoutedEventArgs?e) ????????{ ????????????DialogResult?=?true; ????????} ????????private?void?btnClose_Click(object?sender,?RoutedEventArgs?e) ????????{ ????????????DialogResult?=?false; ????????} ????} }
5)?CropAvatarExample.xaml
?使用如下;
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.CropAvatarExample" ?????????????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:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" ?????????????xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" ?????????????mc:Ignorable="d"? ?????????????d:DesignHeight="450"?d:DesignWidth="800"> ????<Grid> ????????<Grid.ColumnDefinitions> ????????????<ColumnDefinition/> ????????????<ColumnDefinition/> ????????</Grid.ColumnDefinitions> ????????<Button?Content="圖像選擇器"?VerticalAlignment="Center"?HorizontalAlignment="Center"?Click="Button_Click"/> ????????<Image?Grid.Column="1"?Name="MyImage" ???????????????Stretch="Fill"?Width="200"?Height="200"> ????????????<Image.Clip> ????????????????<EllipseGeometry?Center="100,100"?RadiusX="100"?RadiusY="100"/> ????????????</Image.Clip> ????????</Image> ????</Grid> </UserControl>
6)?CropAvatarExample.xaml.cs
?代碼如下;
using?System.Windows.Controls; namespace?WPFDevelopers.Samples.ExampleViews { ????///?<summary> ????///?CropAvatarExample.xaml?的交互邏輯 ????///?</summary> ????public?partial?class?CropAvatarExample?:?UserControl ????{ ????????public?CropAvatarExample() ????????{ ????????????InitializeComponent(); ????????} ????????private?void?Button_Click(object?sender,?System.Windows.RoutedEventArgs?e) ????????{ ????????????var?cropAvatarWindow?=?new?CropAvatarWindow(); ????????????if?(cropAvatarWindow.ShowDialog()?==?true) ????????????{ ????????????????MyImage.Source?=?cropAvatarWindow.CropAvatarImage.Source; ????????????} ????????} ????} }
參考資料
[1]CombinedGeometry
[2]BitmapFrame
[3]CroppedBitmap
[4]Github
[5]Gitee
原文鏈接:https://www.cnblogs.com/yanjinhua/p/16517793.html
相關推薦
- 2022-08-20 Pygame?精準檢測圖像碰撞的問題_python
- 2022-11-05 python?pandas?query的使用方法_python
- 2022-09-13 iOS實現手動和自動屏幕旋轉_IOS
- 2022-04-12 python關閉print輸出信息詳情_python
- 2023-01-15 解讀keras中的正則化(regularization)問題_python
- 2022-05-06 教你使用zabbix?api批量添加數百臺監控主機的方法_zabbix
- 2023-12-11 Spring使用注解開發
- 2022-08-14 Android實現顯示和隱藏密碼功能的示例代碼_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支