簡體   English   中英

如何在Xamarin.froms中的WPF中使用鼠標事件為圖像添加zoomin-zoomout功能

[英]How to add zoomin-zoomout functionalities with mouse events for the image in WPF in xamarin.froms

我正在嘗試使用xamarin.forms在WPF中使用圖像查看器,但沒有找到可啟動的縮放功能。 我只能在Xamarin中獲得WPF或Android。 表單,但找不到WPF與xamarin.forms的組合。 請幫助我實現這一目標。

編輯

我創建了另一個視圖,並能夠使用兩個按鈕進行放大和縮小。

 <ContentPage.Content>
    <ScrollView>
        <StackLayout>
            <Image x:Name="ImageToDisplay"
           HorizontalOptions="Center"
            VerticalOptions="Center"
            Aspect="AspectFill" >
            </Image>
            <StackLayout Orientation="Horizontal" Grid.Row="1" HorizontalOptions="CenterAndExpand">
                <Button Text="ZoomOut" Clicked="ZoomOut"/>
                <Button Text="ZoomIn" Clicked="ZoomIn"/>
            </StackLayout>
        </StackLayout>
    </ScrollView>
</ContentPage.Content>

 private void ZoomIn(object sender, EventArgs e)
    {
        var currentScale = ImageToDisplay.Scale;

        if(currentScale>=1 && currentScale < 5)
        {
            ImageToDisplay.Scale = currentScale + 0.25;
        }
    }

    private void ZoomOut(object sender, EventArgs e)
    {
        var currentScale = ImageToDisplay.Scale;

        if (currentScale >= 1 && currentScale < 5)
        {
            ImageToDisplay.Scale = currentScale - 0.25;
        }
    }

但是在這里,當圖像為“放大”時,圖像的其余部分不可見。 滾動視圖中的圖像未滾動。

您可以自定義Image Behaviors來實現此功能。

創建一個自定義的行為類MultiTouchBehavior.cs

public class MultiTouchBehavior : Behavior<View>
{
    #region Fields

    private double _currentScale = 1, _startScale = 1, _xOffset, _yOffset;

    private PinchGestureRecognizer _pinchGestureRecognizer;

    private PanGestureRecognizer _panGestureRecognizer;

    private ContentView _parent;

    private View _associatedObject;

    #endregion

    /// <summary>
    /// Occurs when BindingContext is changed: used to initialise the Gesture Recognizers.
    /// </summary>
    /// <param name="sender">The sender object.</param>
    /// <param name="e">The event parameters.</param>
    private void AssociatedObjectBindingContextChanged(object sender, EventArgs e)
    {
        _parent = _associatedObject.Parent as ContentView;
        _parent?.GestureRecognizers.Remove(_panGestureRecognizer);
        _parent?.GestureRecognizers.Add(_panGestureRecognizer);
        _parent?.GestureRecognizers.Remove(_pinchGestureRecognizer);
        _parent?.GestureRecognizers.Add(_pinchGestureRecognizer);
    }

    /// <summary>
    /// Cleanup the events.
    /// </summary>
    private void CleanupEvents()
    {
        _pinchGestureRecognizer.PinchUpdated -= OnPinchUpdated;
        _panGestureRecognizer.PanUpdated -= OnPanUpdated;
        _associatedObject.BindingContextChanged -= AssociatedObjectBindingContextChanged;
    }

    /// <summary>
    /// Initialise the events.
    /// </summary>
    private void InitializeEvents()
    {
        CleanupEvents();
        _pinchGestureRecognizer.PinchUpdated += OnPinchUpdated;
        _panGestureRecognizer.PanUpdated += OnPanUpdated;
        _associatedObject.BindingContextChanged += AssociatedObjectBindingContextChanged;
    }

    /// <summary>
    /// Initialise the Gesture Recognizers.
    /// </summary>
    private void InitialiseRecognizers()
    {
        _pinchGestureRecognizer = new PinchGestureRecognizer();
        _panGestureRecognizer = new PanGestureRecognizer();
    }

    /// <summary>
    /// Occurs when Behavior is attached to the View: initialises fields, properties and events.
    /// </summary>
    protected override void OnAttachedTo(View associatedObject)
    {
        InitialiseRecognizers();
        _associatedObject = associatedObject;
        InitializeEvents();

        base.OnAttachedTo(associatedObject);
    }

    /// <summary>
    /// Occurs when Behavior is detached from the View: cleanup fields, properties and events.
    /// </summary>
    protected override void OnDetachingFrom(View associatedObject)
    {
        CleanupEvents();

        _parent = null;
        _pinchGestureRecognizer = null;
        _panGestureRecognizer = null;
        _associatedObject = null;

        base.OnDetachingFrom(associatedObject);
    }

    /// <summary>
    /// Implements Pan/Translate.
    /// </summary>
    /// <param name="sender">The sender object.</param>
    /// <param name="e">The event parameters.</param>
    private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        if (_parent == null)
        {
            return;
        }

        if (!IsTranslateEnabled)
        {
            return;
        }

        switch (e.StatusType)
        {
            case GestureStatus.Running:
                _parent.Content.TranslationX = _xOffset + e.TotalX;
                _parent.Content.TranslationY = _yOffset + e.TotalY;
                break;

            case GestureStatus.Completed:
                _xOffset = _parent.Content.TranslationX;
                _yOffset = _parent.Content.TranslationY;
                break;
        }
    }

    /// <summary>
    /// Implements Pinch/Zoom.
    /// </summary>
    /// <param name="sender">The sender object.</param>
    /// <param name="e">The event parameters.</param>
    private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        if (_parent == null)
        {
            return;
        }

        if (!IsScaleEnabled)
        {
            return;
        }

        switch (e.Status)
        {
            case GestureStatus.Started:
                _startScale = _parent.Content.Scale;
                _parent.Content.AnchorX = 0;
                _parent.Content.AnchorY = 0;

                break;

            case GestureStatus.Running:
                _currentScale += (e.Scale - 1) * _startScale;
                _currentScale = Math.Max(1, _currentScale);

                var renderedX = _parent.Content.X + _xOffset;
                var deltaX = renderedX / _parent.Width;
                var deltaWidth = _parent.Width / (_parent.Content.Width * _startScale);
                var originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

                var renderedY = _parent.Content.Y + _yOffset;
                var deltaY = renderedY / _parent.Height;
                var deltaHeight = _parent.Height / (_parent.Content.Height * _startScale);
                var originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

                var targetX = _xOffset - (originX * _parent.Content.Width) * (_currentScale - _startScale);
                var targetY = _yOffset - (originY * _parent.Content.Height) * (_currentScale - _startScale);

                _parent.Content.TranslationX = targetX.Clamp(-_parent.Content.Width * (_currentScale - 1), 0);
                _parent.Content.TranslationY = targetY.Clamp(-_parent.Content.Height * (_currentScale - 1), 0);

                _parent.Content.Scale = _currentScale;

                break;

            case GestureStatus.Completed:
                _xOffset = _parent.Content.TranslationX;
                _yOffset = _parent.Content.TranslationY;

                break;
        }
    }

    /// <summary>
    /// Initialize the behavior when OnAppearing is executed.
    /// </summary>
    public void OnAppearing()
    {
        AssociatedObjectBindingContextChanged(_associatedObject, null);
    }

    #region IsScaleEnabled property

    /// <summary>
    /// Identifies the <see cref="IsScaleEnabledProperty" /> property.
    /// </summary>
    public static readonly BindableProperty IsScaleEnabledProperty =
        BindableProperty.Create<MultiTouchBehavior, bool>(w => w.IsScaleEnabled, default(bool));

    /// <summary>
    /// Identifies the <see cref="IsScaleEnabled" /> dependency / bindable property.
    /// </summary>
    public bool IsScaleEnabled
    {
        get { return (bool)GetValue(IsScaleEnabledProperty); }
        set { SetValue(IsScaleEnabledProperty, value); }
    }

    #endregion

    #region IsTranslateEnabled property

    /// <summary>
    /// Identifies the <see cref="IsTranslateEnabledProperty" /> property.
    /// </summary>
    public static readonly BindableProperty IsTranslateEnabledProperty =
        BindableProperty.Create<MultiTouchBehavior, bool>(w => w.IsTranslateEnabled, default(bool));

    /// <summary>
    /// Identifies the <see cref="IsTranslateEnabled" /> dependency / bindable property.
    /// </summary>
    public bool IsTranslateEnabled
    {
        get { return (bool)GetValue(IsTranslateEnabledProperty); }
        set { SetValue(IsTranslateEnabledProperty, value); }
    }

    #endregion
}

添加在MultiTouchBehavior.cs中使用的DoubleExtensions.cs

public static class DoubleExtensions
{
    public static double Clamp(this double self, double min, double max)
    {
        return Math.Min(max, Math.Max(self, min));
    }
}

最后,在Xmal中 ,在此處添加兩個Button

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:behaviors="clr-namespace:MultiTouch.Behaviors"
             x:Class="MultiTouch.MainPage">

    <StackLayout>
        <ContentView >
                <Image x:Name="MyImage" Source="desert.jpg">
                    <Image.Behaviors>
                        <behaviors:MultiTouchBehavior IsScaleEnabled="True" IsTranslateEnabled="True" />
                    </Image.Behaviors>
                </Image>
        </ContentView>

        <Button Text="ZoomIn" Clicked="ZoomIn_Clicked"/>
        <Button Text="ZoomOut" Clicked="ZoomOut_Clicked"/>

    </StackLayout>

</ContentPage>

按鈕方式:

private void ZoomIn_Clicked(object sender, System.EventArgs e)
{
    var currentScale = MyImage.Scale;

    if (currentScale >= 1 && currentScale < 5)
    {
        MyImage.Scale = currentScale + 0.25;
    }
}

private void ZoomOut_Clicked(object sender, System.EventArgs e)
{
    var currentScale = MyImage.Scale;

    if (currentScale >= 1 && currentScale < 5)
    {
        MyImage.Scale = currentScale - 0.25;
    }
}

在此處輸入圖片說明 在此處輸入圖片說明

這是示例鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM