I want to move the zoomed image with gyroscope. As you can see in below code I can do this thing by hand and I got a good result. I have to write something inside "Gyroscope_ReadingChanged" to convert gyroscope data to the Content.TranslationX and Content.TranslationY. Any help would be appreciated.
<?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:video="clr-namespace:UbSports.Controls"
xmlns:local="clr-namespace:UbSports.Controls"
x:Class="UbSports.Pages.TestPage">
<local:PinchToZoomContainer VerticalOptions="FillAndExpand">
<local:PinchToZoomContainer.Content>
<Image x:Name="image" Source="waterfront.jpg" />
</local:PinchToZoomContainer.Content>
</local:PinchToZoomContainer>
</ContentPage>
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TestPage: ContentPage
{
public TestPage()
{
InitializeComponent();
}
}
public class PinchToZoomContainer : ContentView
{
public PinchToZoomContainer()
{
Gyroscope.ReadingChanged += Gyroscope_ReadingChanged;
try
{
Gyroscope.Start(SensorSpeed.UI);
}
catch (FeatureNotSupportedException fnsEx)
{
}
catch (Exception ex)
{
}
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(panGesture);
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinchGesture);
}
void Gyroscope_ReadingChanged(object sender, GyroscopeChangedEventArgs e)
{
var data = e.Reading;
if (data.AngularVelocity.X == 0 && data.AngularVelocity.Y == 0) return;
// do something
}
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Started:
startX = e.TotalX;
startY = e.TotalY;
Content.AnchorX = 0;
Content.AnchorY = 0;
break;
case GestureStatus.Running:
var maxTranslationX = Content.Scale * Content.Width - Content.Width;
Content.TranslationX = Math.Min(0, Math.Max(-maxTranslationX, xOffset + e.TotalX - startX));
var maxTranslationY = Content.Scale * Content.Height - Content.Height;
Content.TranslationY = Math.Min(0, Math.Max(-maxTranslationY, yOffset + e.TotalY - startY));
break;
case GestureStatus.Completed:
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
break;
}
}
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…