基于WPF實(shí)現(xiàn)用戶頭像選擇器的示例代碼
實(shí)現(xiàn)思路
制作一個(gè)用戶頭像選擇器仿 WeGame
制作一個(gè)用戶頭像選擇Canvas
為父控件所實(shí)現(xiàn),展示圖片使用Image
,Path
當(dāng)作上方的蒙版;
Canvas
:主要用途方便移動(dòng)Image
,設(shè)置ClipToBounds="True"
裁剪為一個(gè)正方形200x200
做為主要展示區(qū)域;
Image
:展示需要裁剪的圖片;
Path
:CombinedGeometry[1]繪制蒙版大小200x200
效果如下;
當(dāng)選擇一個(gè)本地圖片的時(shí)候判斷寬與高誰更大,誰小就將它更改為200
,另一邊做等比縮放后給到DrawingVisual
繪制一個(gè)新的BitmapFrame[2]給Image
控件做展示;
當(dāng)移動(dòng)圖片的時(shí)候右側(cè)展示當(dāng)前區(qū)域使用CroppedBitmap[3]進(jìn)行裁剪并顯示;
源碼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?開發(fā)者-頭像選擇器"?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="關(guān)閉"?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; ????????????} ????????} ????} }
參考資料
[2]BitmapFrame
[4]Github
[5]Gitee
到此這篇關(guān)于基于WPF實(shí)現(xiàn)用戶頭像選擇器的示例代碼的文章就介紹到這了,更多相關(guān)WPF頭像選擇器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#中將字符串轉(zhuǎn)換為整型的三種解決方法總結(jié)
本篇文章是對C#中將字符串轉(zhuǎn)換為整型的三種解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06DevExpress之ChartControl實(shí)現(xiàn)餅狀圖百分比演示實(shí)例
這篇文章主要介紹了DevExpress之ChartControl實(shí)現(xiàn)餅狀圖百分比演示的方法,實(shí)例講述了窗體與圖形繪制函數(shù)的用法,需要的朋友可以參考下2014-10-10c#使用filesystemwatcher實(shí)時(shí)監(jiān)控文件目錄的添加和刪除
本文主要描述如何通過c#實(shí)現(xiàn)實(shí)時(shí)監(jiān)控文件目錄下的變化,包括文件和目錄的添加,刪除,修改和重命名等操作2014-01-01C# WebService創(chuàng)建、發(fā)布、調(diào)用的實(shí)例講解
下面小編就為大家分享一篇C# WebService創(chuàng)建、發(fā)布、調(diào)用的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12C#靜態(tài)構(gòu)造函數(shù)用法實(shí)例分析
這篇文章主要介紹了C#靜態(tài)構(gòu)造函數(shù)用法,以實(shí)例形式較為詳細(xì)的分析了C#靜態(tài)構(gòu)造函數(shù)的用途、實(shí)現(xiàn)方法及使用技巧,需要的朋友可以參考下2015-06-06C#將HashTable中鍵列表或值列表復(fù)制到一維數(shù)組的方法
這篇文章主要介紹了C#將HashTable中鍵列表或值列表復(fù)制到一維數(shù)組中方法,涉及C#操作HashTable的相關(guān)技巧,需要的朋友可以參考下2015-04-04