첨부 소스 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
4.11MB

▶ DoubleExtension.cs

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
}

 

728x90

 

▶ PinchContentView.cs

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
}

 

300x250

 

▶ MainPage.xaml

<?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>
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요