制作一個用戶頭像選擇器仿 WeGame

?制作一個用戶頭像選擇器仿 WeGame

CropAvatar

作者:WPFDevelopersOrg - 驚鏵

原文鏈接:https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用.NET40

  • Visual Studio 2019;

  • 制作一個用戶頭像選擇Canvas為父控件所實現,展示圖片使用ImagePath當作上方的蒙版;

  • Canvas:主要用途方便移動Image,設置ClipToBounds="True"裁剪為一個正方形200x200做為主要展示區域;

  • Image:展示需要裁剪的圖片;

c9b07db74e5383aeeabc61af6135cfa7.png
  • Path:CombinedGeometry[1]繪制蒙版大小200x200效果如下;

bf0fe795785019aa7512bdf50942cf13.png
  • 當選擇一個本地圖片的時候判斷寬與高誰更大,誰小就將它更改為200 ,另一邊做等比縮放后給到DrawingVisual繪制一個新的BitmapFrame[2]Image控件做展示;

  • 當移動圖片的時候右側展示當前區域使用CroppedBitmap[3]進行裁剪并顯示;

  • 源碼Github[4]Gitee[5]

cd67c09d9712dfb1349e510628b4379c.gif1)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: https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.media.combinedgeometry?view=netframework-4.0

[2]

BitmapFrame: https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.media.imaging.bitmapframe?view=windowsdesktop-6.0

[3]

CroppedBitmap: https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.media.imaging.croppedbitmap?view=windowsdesktop-6.0

[4]

Github: https://github.com/WPFDevelopersOrg/WPFDevelopers

[5]

Gitee: https://gitee.com/WPFDevelopersOrg/WPFDevelopers

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280796.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280796.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280796.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PS2019進階筆記(二)

云端網校筆記&#xff08;PS2015&#xff09; 一、圖層混合模式 圖層面板上的左上角&#xff0c;默認正常 混合下面圖層&#xff0c;下面正片&#xff08;如模特&#xff09;。 最常用是&#xff1a;不透明度 溶解&#xff1a;需調節透明度 變暗組&#xff1a; 亮區域去除…

Html5里frameSet不在使用的替代方法,使用ifram

原來得使用方式&#xff1a; <frameset rows"100,*" frameborder"0"><frame name"header" src"header.aspx"></frame><frameset cols"15%, *"><frame name"menu" src"left.aspx&…

網曝南方電網搞末位淘汰和裁員,給各下屬單位強制規定辭退率和降崗降級率!...

電網作為壟斷性國企&#xff0c;在人們心中一向是好單位的代名詞&#xff0c;但最近卻有網友曝光南方電網搞末位淘汰和裁員&#xff0c;給各單位下了辭退率和降崗降級率&#xff0c;每個單位都要開除一部分人&#xff0c;或者把一部分人崗級降下來。有南方電網員工馬上跑出來辟…

二維數組中的查找

2019獨角獸企業重金招聘Python工程師標準>>> 題目 在一個二維數組中&#xff0c;每一行中的數都按照從左到右、從上到下的遞增順序排列。要求輸入一個整數&#xff0c;判斷數組中是否存在該整數 實現代碼 function find($matrix, $rows, $columns, $key) {//TODO 參…

C# JObject轉換JSON文件相關處理

一、JObject.Parse 1.把整個json文件字符串轉化成JObject格式。 JObject jsonData JObject.Parse(jsonString); 2.逐級轉換成JObject 最低級是"Device": "Windowsr"&#xff0c;字典。 jsonData JObject.Parse(jsonData[jsonName][jsonIndex].ToStr…

通過修改然后commit的方式創建自己的鏡像

創建自己的鏡像&#xff1a;通過現有的鏡像來創建自己的鏡像。1、首先拉取一個鏡像到本地$ sudo docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEubuntu 12.04 5b117edd0b76 11 months…

hdu6103[尺取法] 2017多校6

/*hdu6103[尺取法] 2017多校6*/ #include <bits/stdc.h> using namespace std; int T, m; char str[20005]; void solve() {int ans 0;int n strlen(str);for (int i 0; i < n; i) {int l 0, r 0, p1 i, p2 i 1, cost 0;while (p1 - r > 0 && p2 …

藍牙追蹤_如何使用藍牙追蹤器跟蹤您的東西

藍牙追蹤We’ve all done it: you misplace something important and you spend a lot of time (with a lot of stress) backtracking to locate it again. With Bluetooth tracking devices you can make the hunt a lot easier, less stressful, and even avoid losing the t…

遠程訪問CENTOS的MYSQL數據庫設置

遠程訪問CENTOS的MYSQL數據庫設置 mysql -u root grant all privileges on *.* to root%identified by root; 后面的root是root用戶的密碼 grant all privileges on *.* to rootlocalhostidentified by root; mysql -u root -p

ShardingCore 7.0 版本發布

NCC ShardingCore 是一款 EntityFramework Core based 高性能、輕量級、分表分庫、讀寫分離解決方案&#xff0c;具有零依賴、零學習成本、零業務代碼入侵等特點。ShardingCore 7.0 已于近期發布。從 ShardingCore 7.0 開始&#xff0c;啟用版本號第二位來對應不同的 EFCore 版…

搬運 centos7.2 apache 綁定二級目錄 訪問依然是apache頁面

<VirtualHost *:80>ServerName xx.comDocumentRoot /var/www/html/xx</VirtualHost> 轉載于:https://www.cnblogs.com/kiimi/p/8662490.html

django09: ORM以及CSRF(舊筆記)

ORM相當于程序里的數據庫操作 ORM(一) https://www.cnblogs.com/liwenzhou/p/8688919.html ORM(二) https://www.cnblogs.com/liwenzhou/p/8660826.html CSRF:防止網站請求偽造&#xff0c;即釣魚網 在Form表達添加&#xff1a;{% csrf_toker %}

vba發送郵件 簽名_如何更改“從Windows 10的郵件發送”簽名

vba發送郵件 簽名The Windows 10 Mail app is a decent email client that allows you to add other email accounts in addition to your Microsoft accounts. You’ll notice, though, that any emails you write in the Mail app have a default signature. Windows 10 Mail…

JAVA_SE基礎——24.面向對象的內存分析

黑馬程序猿入學blog ... 接著上一章的代碼&#xff1a; //車類 class Car{//事物的公共屬性使用成員變量描寫敘述。String name; //名字的屬性 String color; //顏色屬性 int wheel; //輪子數 //事物的公共行為使用函數描寫敘述。 public void run(){ System.out.println(name&…

煮茶社區AVR開發板第二版[轉]

原圖:http://blossom.cnblogs.com/gallery/image/21891.html

[Kogel.Subscribe.Mssql]SQL Server增量訂閱,數據庫變更監聽

此框架是SQL Server增量訂閱&#xff0c;用來監聽增刪改數據庫數據變更目前僅支持SQL Server&#xff0c;后續會支持MySQL和Oracle&#xff0c;Nuget上可以下載安裝或者使用Nuget命令添加包dotnet add package Kogel.Subscribe.Mssql --version 0.0.0.1可以用來處理DB主從同步&…

java instanceof運算符

instanceof 運算符 該運算符用于操作對象實例&#xff0c;檢查該對象是否是一個特定類型&#xff08;類類型或接口類型&#xff09;。 instanceof運算符使用格式如下&#xff1a; ( Object reference variable ) instanceof (class/interface type) 如果運算符左側變量所指的對…

C# XML添加刪除/SelectNodes/xpath

SelectNodes中的XPath //從當前節點的兒子節點中選擇名稱為 item 的節點。 SelectNodes("item")//從根節點的兒子節點中選擇名稱為 item 的節點。 SelectNodes("/item")// 從任意位置的節點上選擇名稱為 item 的節點。要重點突出這個任意位置&#xff0c;…

Python中*args 和**kwargs的用法

http://blog.csdn.net/chenjinyu_tang/article/details/8136841 好久沒有學習python了&#xff0c;應為工作的需要&#xff0c;再次拾起python&#xff0c;喚起記憶。 當函數的參數不確定時&#xff0c;可以使用*args 和**kwargs&#xff0c;*args 沒有key值&#xff0c;**kwar…

MFC載入JPG圖片

## 1.定義畫圖函數 HRESULT CIPCamDlg::draw(char *lpImageFile, HWND hWnd, int nScrWidth, int nScrHeight) {HDC hDC_Temp::GetDC(hWnd);IPicture *pPic; IStream *pStm;BOOL bResult;HANDLE hFileNULL; DWORD dwFileSize,dwByteRead;hFileCreateFile(lpImageFile,GENERIC_R…