[C#/MAUI/.NET6] PinchGestureRecognizer 클래스 : PinchUpdated 업데이트를 사용해 핀치 처리하기 (기능 개선)
■ PinchGestureRecognizer 클래스의 PinchUpdated 업데이트를 사용해 핀치를 처리하는 방법을 보여준다. (기능 개선) ▶ DoubleExtension.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
namespace TestProject; /// <summary> /// 배정도 실수 확장 /// </summary> public static class DoubleExtension { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 고정하기 - Clamp(sourceValue, minimumValue, maxiumValue) /// <summary> /// 고정하기 /// </summary> /// <param name="sourceValue">소스 값</param> /// <param name="minimumValue">최소 값</param> /// <param name="maxiumValue">최대 값</param> /// <returns>고정 값</returns> public static double Clamp(this double sourceValue, double minimumValue, double maxiumValue) { return Math.Min (maxiumValue, Math.Max (sourceValue, minimumValue)); } #endregion } |
▶ PinchContentView.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
namespace TestProject; /// <summary> /// 핀치 컨텐트 뷰 /// </summary> public class PinchContentView : Frame { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 현재 스케일 /// </summary> private double currentScale = 1; /// <summary> /// 시작 스케일 /// </summary> private double startScale = 1; /// <summary> /// 오프셋 X /// </summary> private double officeX = 0; /// <summary> /// 오프셋 Y /// </summary> private double officeY = 0; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - PinchContentView() /// <summary> /// 생성자 /// </summary> public PinchContentView() { Padding = new Thickness(0); IsClippedToBounds = true; PinchGestureRecognizer recognizer = new PinchGestureRecognizer(); recognizer.PinchUpdated += recognizer_PinchUpdated; GestureRecognizers.Add(recognizer); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 인식기 핀치 업데이트시 처리하기 - recognizer_PinchUpdated(sender, e) /// <summary> /// 인식기 핀치 업데이트시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void recognizer_PinchUpdated(object sender, PinchGestureUpdatedEventArgs e) { if(e.Status == GestureStatus.Started) { this.startScale = Content.Scale; Content.AnchorX = 0; Content.AnchorY = 0; } else if(e.Status == GestureStatus.Running) { this.currentScale += (e.Scale - 1) * this.startScale; this.currentScale = Math.Max(1, this.currentScale); double renderedX = Content.X + this.officeX; double deltaX = renderedX / Width; double deltaWidth = Width / (Content.Width * this.startScale); double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth; double renderedY = Content.Y + this.officeY; double deltaY = renderedY / Height; double deltaHeight = Height / (Content.Height * this.startScale); double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight; double targetX = this.officeX - (originX * Content.Width ) * (this.currentScale - this.startScale); double targetY = this.officeY - (originY * Content.Height) * (this.currentScale - this.startScale); Content.TranslationX = targetX.Clamp(-Content.Width * (this.currentScale - 1), 0); Content.TranslationY = targetY.Clamp(-Content.Height * (this.currentScale - 1), 0); Content.Scale = this.currentScale; } else if(e.Status == GestureStatus.Completed) { this.officeX = Content.TranslationX; this.officeY = Content.TranslationY; } } #endregion } |
▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TestProject"> <local:PinchContentView HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="300" HeightRequest="300"> <Image Source="source.png" WidthRequest="300" HeightRequest="300" Aspect="Fill" /> </local:PinchContentView> </ContentPage> |
TestProject.zip