Image only zoom in but not zoom out in Xamarin forms - c#

I have content page which contain photo. I wanted to add the zoom in and zoom out options however when i tried to add the pinch gesture it is only zoom in but not zoom out? how can I add the zoom out options?
here is my XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ComplexInstructionApp.ShowProgram"
Title="dsa">
<ContentPage.Content>
</ContentPage.Content>
<Grid>
<Image x:Name="IMI" Aspect="Fill"
RelativeLayout.WidthConstraint=
"{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.HeightConstraint=
"{ConstraintExpression Type=RelativeToParent, Property=Height}"
/>
</Grid>
</ContentPage>
and here is my code:
public partial class ShowProgram : ContentPage
{
private double currentScale = 1;
private double startScale = 1;
private double xOffset = 0;
private double yOffset = 0;
public ShowProgram(string txt)
{
InitializeComponent();
switch (txt)
{
case "קובני":
IMI.Source = "Cuben_Expend.png";
break;
case "קובני מצומצם":
IMI.Source = "Cuben_short.png";
break;
case "אל איי":
IMI.Source = "LA_Expend.png";
break;
case "אל איי מצומצם":
IMI.Source = "LA_short.png";
break;
case "בצ'אטה":
IMI.Source = "bachata.png";
break;
case "זוק":
IMI.Source = "zouk.png";
break;
}
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += (s, e) =>
{
if (e.Status == GestureStatus.Started)
{
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = Clamp1(targetX ,- Content.Width * (currentScale - 1), 0);
Content.TranslationY = Clamp1(targetY, -Content.Height * (currentScale - 1), 0);
// Apply scale factor.
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
};
IMI.GestureRecognizers.Add(pinchGesture);
}
public double Clamp1(double self, double min, double max)
{
return Math.Min(max, Math.Max(self, min));
}
}

Related

Image flickering while zooming while using PinchGestureRecognizer

I use the below code to place an <Image> and <Image.GestureRecognizers> to make the zoom functionality.
The code behind for the event PinchUpdated="PinchGestureRecognizer_PinchUpdated" is also provided.
The zoom function works, but too much flickering while pinching.
XAML :
<Image
Grid.Column="0"
Grid.Row="0"
x:Name="pageIterator"
Grid.ColumnSpan="3">
<Image.GestureRecognizers>
<PinchGestureRecognizer PinchUpdated="PinchGestureRecognizer_PinchUpdated"></PinchGestureRecognizer>
</Image.GestureRecognizers>
</Image>
Code behind :
private void PinchGestureRecognizer_PinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
if (e.Status == GestureStatus.Started)
{
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);
// Apply scale factor.
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
You should move the below lines out of PinchGestureRecognizer_PinchUpdated method,otherwise you're essentially initializing these values every time you fire.
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
private void PinchGestureRecognizer_PinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);
// Apply scale factor.
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}

C# GMap: How to draw a 120 degree beam angle on a map

how can I add a polygon to the map as in the picture below? From a certain point of coordinates should open a polygon long, for example, 1 kilometer and a 120-degree opening angle.
https://i.ibb.co/ZLKgvJs/image.png
private void CreateCircle(Double lat, Double lon, double radius, int ColorIndex)
{
GMapOverlay markers = new GMapOverlay(mygmap, "markers");
PointLatLng point = new PointLatLng(lat, lon);
int segments = 1080;
List<PointLatLng> gpollist = new List<PointLatLng>();
for (int i = 0; i < segments; i++)
{
gpollist.Add(FindPointAtDistanceFrom(point, i * (Math.PI / 180), radius / 1000));
}
GMapPolygon polygon = new GMapPolygon(gpollist, "Circle");
switch (ColorIndex)
{
case 1:
polygon.Fill = new SolidBrush(Color.FromArgb(80, Color.Red));
break;
case 2:
polygon.Fill = new SolidBrush(Color.FromArgb(80, Color.Orange));
break;
case 3:
polygon.Fill = new SolidBrush(Color.FromArgb(20, Color.Aqua));
break;
default:
MessageBox.Show("No search zone found!");
break;
}
polygon.Stroke = new Pen(Color.Red, 1);
markers.Polygons.Add(polygon);
mygmap.Overlays.Add(markers);
}
public static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
{
const double radiusEarthKilometres = 6371.01;
var distRatio = distanceKilometres / radiusEarthKilometres;
var distRatioSine = Math.Sin(distRatio);
var distRatioCosine = Math.Cos(distRatio);
var startLatRad = DegreesToRadians(startPoint.Lat);
var startLonRad = DegreesToRadians(startPoint.Lng);
var startLatCos = Math.Cos(startLatRad);
var startLatSin = Math.Sin(startLatRad);
var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
var endLonRads = startLonRad + Math.Atan2(Math.Sin(initialBearingRadians) * distRatioSine * startLatCos, distRatioCosine - startLatSin * Math.Sin(endLatRads));
return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
}
public static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI / 180;
return degrees * degToRadFactor;
}
public static double RadiansToDegrees(double radians)
{
const double radToDegFactor = 180 / Math.PI;
return radians * radToDegFactor;
}
My code can only draw a circle. Can it be changed so that it can draw a polygon from a certain point of coordinates with an indication of the direction, distance of drawing and the angle of aperture?
Try to break your circle into 20,30,40 or 50 points, display only the points you want and draw a polyline for each 2 points
int n = 20; //number of points
for(i = 0; i<n ;i++)
{
angle = i * (360/n);
point.x = x_center + r * cos(angle);
point.y = y_center + r * sin(angle);
}

Xamarin add Scale/Rotate to ContentView

I have a question.
I created a CustomView where I can drag/drop the view inside, but now I also want to add a scale/rotate function to it. Now here is the OnTouchEvent that created to move the view inside:
public override bool OnTouchEvent(MotionEvent e)
{
float x = e.RawX;
float y = e.RawY;
var dragView = Element as DraggableView.DraggableView;
switch (e.Action)
{
case MotionEventActions.Down:
if (dragView.DragMode == DragMode.Touch)
{
if (!touchedDown)
{
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
}
TextMoved = false;
touchedDown = true;
stopwatch.Start();
}
dX = x - this.GetX();
dY = y - this.GetY();
break;
case MotionEventActions.Move:
if (touchedDown)
{
if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Horizontal)
{
SetX(x - dX);
}
if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Vertical)
{
SetY(y - dY);
}
TextMoved = true;
}
break;
case MotionEventActions.Up:
touchedDown = false;
if(TextMoved == true)
{
dragView.DragEnded();
}
else
{
MessagingCenter.Send<object, DraggableView.DraggableView>(this, "EditSelectedText", dragView);
}
break;
case MotionEventActions.Cancel:
touchedDown = false;
break;
}
return base.OnTouchEvent(e);
}
But now I also need the Scale/Rotate function.
The problem is that I already created it for my skiasharp bitmaps, but this isn't skiasharp, so I can't use that.
How can I implement this function in a OnTouchEvent without skiasharp?
There is a xamarin-forms-samples about ScaleAndRotate , however it is not related to TouchEvent .I found a way by using PanGestureRecognizer and PinchGestureRecognizer to implement it .
Create a ScaleAndRotateContainer ContentView which contains PanGestureRecognizer and PinchGestureRecognizer :
public class ScaleAndRotateContainer : ContentView
{
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
double rotateNum = 1;
public ScaleAndRotateContainer()
{
var pinchGesture = new PinchGestureRecognizer ();
pinchGesture.PinchUpdated += OnPinchUpdated;
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += PanGesture_PanUpdated;
GestureRecognizers.Add (pinchGesture);
GestureRecognizers.Add(panGesture);
}
private void PanGesture_PanUpdated(object sender, PanUpdatedEventArgs e)
{
rotateNum++;
this.RotateTo(rotateNum);
this.AnchorX = 0.5;
this.AnchorY = 0.5;
}
void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started) {
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running) {
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max (1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp (-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp (-Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed) {
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}
Then use it in Xaml for ContentPage :
xmlns:local="clr-namespace:PinchGesture;assembly=YourNameSpace"
<local:ScaleAndRotateContainer>
<local:ScaleAndRotateContainer.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center" >
<Label Text="Hello Xamarin.Forms!" />
<Image Source="waterfront.jpg" />
</StackLayout>
</local:ScaleAndRotateContainer.Content>
</local:ScaleAndRotateContainer>
The effect :

how to enable scrolling when zoom in and zoom out on a content page in xamarin forms

i am trying to zoom in and zoom out on a content page using xamarin.forms.
I am able zoom in and zoom out but the problem is scrolling is not working.
i want zoom an image. with this code zooming is working perfectly. But while zooming i am not able to see full image. i must scroll to view the rest of the image. for that i need to scroll. but scrolling is not working.
XAML
xmlns:helper="clr-namespace:KPGTC.Deals.Mobile.Helpers"
<helper:PinchToZoomContainer>
<helper:PinchToZoomContainer.Content>
<Image x:Name="img_Popup"/>
</helper:PinchToZoomContainer.Content>
</helper:PinchToZoomContainer>
Code:
public class PinchToZoomContainer : ContentView
{
double MIN_SCALE = 1;
double MAX_SCALE = 4;
double startScale = 1;
double currentScale = 1;
double xOffset = 0;
double yOffset = 0;
bool _isActive = false;
public PinchToZoomContainer()
{
DependencyService.Get<IHelpers>().ShowAlert("Double-tap to zoom");
//var _pinchGesture = new PinchGestureRecognizer();
//_pinchGesture.PinchUpdated += OnPinchUpdated;
//GestureRecognizers.Add(_pinchGesture);
var _tapGesture = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
_tapGesture.Tapped += On_Tapped;
GestureRecognizers.Add(_tapGesture);
var _panGesture = new PanGestureRecognizer();
_panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(_panGesture);
TranslationX = 0;
TranslationY = 0;
_isActive = false;
}
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (_isActive)
{
if (e.TotalX > 0)
{
if (e.TotalX > 2)
{
TranslationX += 15;
}
}
else
{
if (e.TotalX < -2)
{
TranslationX -= 15;
}
}
}
}
private void On_Tapped(object sender, EventArgs e)
{
if (Scale > MIN_SCALE)
{
_isActive = false;
this.ScaleTo(MIN_SCALE, 250, Easing.CubicInOut);
this.TranslateTo(0, 0, 250, Easing.CubicInOut);
}
else
{
_isActive = true;
AnchorX = AnchorY = 0.5;
this.ScaleTo(MAX_SCALE, 250, Easing.CubicInOut);
}
}
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;
}
}
}
Alright, this was quite a tough one and admittedly I don't understand fully how I made it, but I made it.
Some thoughts:
You mixed the translation of the container and the content, which is quite tricky to handle - if this is possible at all
When panning, you added 15 every time the pan event was raised, but there is a better way: Just store the initial offset of the content and then add the TotalX and TotalY respectively to the TranslationX and the TranslationY of the content (this was the easy part)
Panning while zooming was quite hard to get right and I had to find it out by trial and error
Basically you have to store the origin of the pinch gesture when the gesture starts and calculate the diff between the original origin and the current origin
Then you have to add the diff (multiplied by the with and height respectively of the control) to the target translation
Here is the code for the panning:
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (e.StatusType == GestureStatus.Started)
{
this.xOffset = this.Content.TranslationX;
this.yOffset = this.Content.TranslationY;
}
if (e.StatusType != GestureStatus.Completed
&& e.StatusType != GestureStatus.Canceled)
{
this.Content.TranslationX = this.xOffset + e.TotalX;
this.Content.TranslationY = this.yOffset + e.TotalY;
}
if (e.StatusType == GestureStatus.Completed)
{
this.xOffset = this.Content.TranslationX;
this.yOffset = this.Content.TranslationY;
}
}
And here for the pinching
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
this.startScale = this.Content.Scale;
this.Content.AnchorX = 0;
this.Content.AnchorY = 0;
this.startScaleOrigin = e.ScaleOrigin;
}
if (e.Status == GestureStatus.Running)
{
var originDiff = PinchToZoomContainer.CalculateDiff(e.ScaleOrigin, this.startScaleOrigin);
this.currentScale += (e.Scale - 1) * this.startScale;
this.currentScale = Math.Max(1, this.currentScale);
double renderedX = this.Content.X + this.xOffset;
double deltaX = renderedX / this.Width;
double deltaWidth = this.Width / (this.Content.Width * this.startScale);
double originX = (this.startScaleOrigin.X - deltaX) * deltaWidth;
double renderedY = this.Content.Y + this.yOffset;
double deltaY = renderedY / this.Height;
double deltaHeight = this.Height / (this.Content.Height * this.startScale);
double originY = (startScaleOrigin.Y - deltaY) * deltaHeight;
double targetX = this.xOffset - ((originX) * this.Content.Width) * (this.currentScale - this.startScale) - originDiff.X * this.Content.Width;
double targetY = this.yOffset - ((originY) * this.Content.Height) * (this.currentScale - this.startScale) - originDiff.Y * this.Content.Height;
this.Content.TranslationX = targetX.Clamp(-this.Content.Width * (this.currentScale - 1), 0);
this.Content.TranslationY = targetY.Clamp(-this.Content.Height * (this.currentScale - 1), 0);
this.Content.Scale = this.currentScale;
}
if (e.Status == GestureStatus.Completed)
{
this.xOffset = this.Content.TranslationX;
this.yOffset = this.Content.TranslationY;
}
}
(Of course you have to add Point startScaleOrigin to your class).
Finally you need the method to calculate the distance between two points
private static Point CalculateDiff(Point first, Point second)
{
return second.Offset(-first.X, -first.Y);
}
Unfortunately I did not manage to get the tapping right, but I think you should be able to figure it out from here.

Numeric Extensions.Clamp(double, double, double)' is inaccessible due to its protection level in xamarin forms class

I am working on adding pitch to zoom into my xamarin forms content page and I'm using this example and i'm getting this error upon running the app on my phone:
Severity Code Description Project File Line Suppression State
Error CS0122 'NumericExtensions.Clamp(double, double, double)' is inaccessible due to its protection level AppName.Forms C:\TFSMOBILE\AppName.NETStandard\AppName.Forms\Pages\PinchToZoomContainer.cs 55 Active
here's the code for the PinchToZoomContainer:
using System;
using Xamarin.Forms;
namespace AppName.Forms.Pages
{
public class PinchToZoomContainer : ContentView
{
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
public PinchToZoomContainer()
{
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinchGesture);
}
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
//error 1:
Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
//error 2:
Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}
}
any help would be amazing!!
Thanks in advance! :)
That project you referenced on GitHub is using its own Clamp function and not the internal Forms-based one and due to the error I would assume you are missing this class:
using System;
namespace PinchGesture
{
public static class DoubleExtensions
{
public static double Clamp (this double self, double min, double max)
{
return Math.Min (max, Math.Max (self, min));
}
}
}
Re: https://github.com/xamarin/xamarin-forms-samples/blob/290d8947432fef55852bf381dcaec393d638f150/WorkingWithGestures/PinchGesture/PinchGesture/Extensions/DoubleExtensions.cs
in the current release version of Xamarin Forms, NumericExtensions is internal. It will be changed to public in a future release.
In the meantime, you can easily implement Clamp yourself
return Math.Min(max, Math.Max(value, min));

Categories

Resources