Découper une image basse résolution à l’aide de Transforms et l’affecter à mon contrôle utilisateur

Je travaille sur une application Windows 8.1 RT dans laquelle l’utilisateur charge une image avec Stretch = Uniform . L’image peut être aussi petite que possible et aussi grande que possible. La coupure se produit dans mon contrôle d’utilisateur et mon contrôle d’utilisateur apparaît lorsque je tape / appuie longuement sur l’écran / l’image. La coupure se produit lorsque, lorsque je touche et maintient le doigt et la souris sur l’image qui se trouve à l’arrière-plan, je la déplace.

Les problèmes auxquels je suis confronté sont

  1. Chaque fois que l’application est chargée pour la première fois sur Emulator, et pour la première fois lorsque vous appuyez et maintenez enfoncé, le contrôle de l’utilisateur apparaît en haut à gauche de l’écran, puis vient au-dessus de ma zone cliquée / en attente. Ce dont j’ai besoin, c’est qu’il apparaisse toujours partout où je clique et que je tiens et quand je clique et que je tiens En relâchant le doigt / souris, il devrait s’effondrer.

  2. J’utilise le centre transform. Je veux que la région (le pixel) où ma souris est actuellement affichée soit exactement au centre du contrôle utilisateur, Si je charge une image de petite résolution de 480 * 800 ou même plus petite, la région de ma souris n’entre pas dans le centre. Pour être plus clair, imaginons que je tape et tiens sur la cornée de l’œil humain. La cornée doit être affichée au centre du contrôle utilisateur et la zone située au-dessus et au-dessous devrait couvrir le rest de la pièce.

    1. Je ne souhaite pas que mon contrôle dépasse les limites de l’image. Si ma souris se trouve au dernier pixel de l’image, une partie de l’image et une partie de l’arrière-plan doivent être affichées.
  3. Je dois faire pivoter le contrôle comme indiqué dans la vidéo Trouvez le code complet ci-dessous.

MainPage.XAML

      

MAINPAGE.XAML.CS

 using System; using System.Diagnostics; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media.Imaging; namespace App78 { public sealed partial class MainPage : Page { private double zoomScale = 2; private double pointerX = 0; private double pointerY = 0; private const double MinZoomScale = .25; private const double MaxZoomScale = 32; public MainPage() { this.InitializeComponent(); var bi = (BitmapImage)BigImage.Source; bi.ImageOpened += bi_ImageOpened; this.SizeChanged += MainPage_SizeChanged; } void MainPage_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e) { this.UpdateImageLayout(); } void bi_ImageOpened(object sender, Windows.UI.Xaml.RoutedEventArgs e) { this.UpdateImageLayout(); } private void UpdateImageLayout() { var bi = (BitmapImage)BigImage.Source; if (bi.PixelWidth < this.LayoutGrid.ActualWidth && bi.PixelHeight < this.LayoutGrid.ActualHeight) { this.BigImage.Stretch = Stretch.None; } else { this.BigImage.Stretch = Stretch.Uniform; } this.UpdateMagnifier(); } private void LayoutGrid_OnPointerMoved(object sender, PointerRoutedEventArgs e) { //DV: If pointer is not in contact we can ignore it if (!e.Pointer.IsInContact) { return; } var point = e.GetCurrentPoint(this.LayoutGrid); this.pointerX = point.Position.X; this.pointerY = point.Position.Y; this.UpdateMagnifier(); } private void UpdateMagnifier() { var bi = (BitmapImage)BigImage.Source; double offsetX = 0; double offsetY = 0; double imageScale = 1; var imageRatio = (double)bi.PixelWidth / bi.PixelHeight; var gridRatio = this.LayoutGrid.ActualWidth / this.LayoutGrid.ActualHeight; if (bi.PixelWidth < this.LayoutGrid.ActualWidth && bi.PixelHeight < this.LayoutGrid.ActualHeight) { offsetX = 0.5 * (this.LayoutGrid.ActualWidth - bi.PixelWidth); offsetY = 0.5 * (this.LayoutGrid.ActualHeight - bi.PixelHeight); //imageScale = 1; - remains } else if (imageRatio  0) { zoomScale = Math.Max(MinZoomScale, Math.Min(MaxZoomScale, zoomScale * 1.2)); } else { zoomScale = Math.Max(MinZoomScale, Math.Min(MaxZoomScale, zoomScale / 1.2)); } this.UpdateMagnifier(); } //DV: Holding usually only works with touch https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.uielement.holding.aspx?f=255&MSPPError=-2147217396 private void LayoutGrid_Holding(object sender, HoldingRoutedEventArgs e) { // } //DV: pointer pressed supports both mouse and touch but fires immeadiatley. You'll have to figure out a delay strategy or using holding for touch and right click for mouse private void LayoutGrid_OnPointerPressed(object sender, PointerRoutedEventArgs e) { MagnifierTip.Visibility = Windows.UI.Xaml.Visibility.Visible; } //DV: pointer released supports both mouse and touch. private void LayoutGrid_OnPointerReleased(object sender, PointerRoutedEventArgs e) { MagnifierTip.Visibility = Windows.UI.Xaml.Visibility.Collapsed; } } } 

Loupe.XAML

                          

Pour plus de facilité, le projet peut être téléchargé ici . Pour une meilleure compréhension, j’aimerais que vous voyiez cette vidéo . C’est ce que j’ai exactement besoin de mettre en œuvre.

Je l’ai eu avec quelques modifications et sortinggonomésortinge ici .

MainPage.xaml

       

MainPage.xaml.cs

 using System; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media.Imaging; namespace MagnifierApp { public sealed partial class MainPage : Page { private double zoomScale = 2; private double pointerX = 0; private double pointerY = 0; private const double MinZoomScale = .25; private const double MaxZoomScale = 32; private bool isFirst = true; public MainPage() { this.InitializeComponent(); var bi = (BitmapImage)BigImage.Source; bi.ImageOpened += bi_ImageOpened; this.SizeChanged += MainPage_SizeChanged; } void MainPage_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e) { this.UpdateImageLayout(); } void bi_ImageOpened(object sender, Windows.UI.Xaml.RoutedEventArgs e) { this.UpdateImageLayout(); } private void UpdateImageLayout() { var bi = (BitmapImage)BigImage.Source; if (bi.PixelWidth < this.LayoutGrid.ActualWidth && bi.PixelHeight < this.LayoutGrid.ActualHeight) { this.BigImage.Stretch = Stretch.None; } else { this.BigImage.Stretch = Stretch.Uniform; } this.UpdateMagnifier(); } private void LayoutGrid_OnPointerMoved(object sender, PointerRoutedEventArgs e) { if (!e.Pointer.IsInContact) { return; } var point = e.GetCurrentPoint(this.LayoutGrid); this.pointerX = point.Position.X; this.pointerY = point.Position.Y; this.UpdateMagnifier(); } private void LayoutGrid_OnPointerWheelChanged(object sender, PointerRoutedEventArgs e) { if (e.GetCurrentPoint(this.LayoutGrid).Properties.MouseWheelDelta > 0) { zoomScale = Math.Max(MinZoomScale, Math.Min(MaxZoomScale, zoomScale * 1.2)); } else { zoomScale = Math.Max(MinZoomScale, Math.Min(MaxZoomScale, zoomScale / 1.2)); } this.UpdateMagnifier(); } private void LayoutGrid_OnPointerPressed(object sender, PointerRoutedEventArgs e) { if (!e.Pointer.IsInContact) { return; } var point = e.GetCurrentPoint(this.LayoutGrid); this.pointerX = point.Position.X; this.pointerY = point.Position.Y; this.UpdateMagnifier(); MagnifierTip.Visibility = Windows.UI.Xaml.Visibility.Visible; } private void LayoutGrid_OnPointerReleased(object sender, PointerRoutedEventArgs e) { MagnifierTip.Visibility = Windows.UI.Xaml.Visibility.Collapsed; } private void UpdateMagnifier() { var bi = (BitmapImage)BigImage.Source; double offsetX; double offsetY; double imageScale; CalculateImageScaleAndOffsets(bi, out offsetX, out offsetY, out imageScale); MagnifierTip.PositionTransform.X = (-this.pointerX + offsetX) / imageScale; MagnifierTip.PositionTransform.Y = (-this.pointerY + offsetY) / imageScale; MagnifierTip.ZoomTransform.ScaleX = imageScale * zoomScale; MagnifierTip.ZoomTransform.ScaleY = imageScale * zoomScale; MagnifierTip.CenterTransform.X = MagnifierTip.MagnifierEllipse.ActualWidth / 2 - MagnifierTip.MagnifierEllipse.StrokeThickness / 2; MagnifierTip.CenterTransform.Y = MagnifierTip.MagnifierEllipse.ActualHeight / 2 - MagnifierTip.MagnifierEllipse.StrokeThickness / 2; MagnifierTip.MagnifierTranslateTransform.X = this.pointerX - (MagnifierTip.ActualWidth / 2); MagnifierTip.MagnifierTranslateTransform.Y = this.pointerY - (MagnifierTip.ActualHeight); bool tooHigh = MagnifierTip.MagnifierTranslateTransform.Y < 0; bool tooLeft = MagnifierTip.MagnifierTranslateTransform.X < 0; bool tooRight = MagnifierTip.MagnifierTranslateTransform.X + MagnifierTip.ActualWidth > this.LayoutGrid.ActualWidth; if (tooHigh || tooLeft || tooRight) { double angle = 0.0; if (tooLeft && !tooHigh) { var dx = -MagnifierTip.MagnifierTranslateTransform.X; var r = MagnifierTip.ActualHeight - MagnifierTip.ActualWidth / 2; var arad = Math.Asin(dx / r); angle = arad * 180 / Math.PI; } else if (tooLeft && tooHigh) { var dx = -MagnifierTip.MagnifierTranslateTransform.X; var dy = -MagnifierTip.MagnifierTranslateTransform.Y; var r = MagnifierTip.ActualHeight - MagnifierTip.ActualWidth / 2; var arad1 = Math.Asin(dx / r); var arad2 = Math.Acos((r - dy) / r); var arad = Math.Max(arad1, arad2); angle = arad * 180 / Math.PI; } else if (tooHigh && !tooRight) { var dy = -MagnifierTip.MagnifierTranslateTransform.Y; var r = MagnifierTip.ActualHeight - MagnifierTip.ActualWidth / 2; var arad = Math.Acos((r - dy) / r); if (MagnifierTip.MagnifierTranslateTransform.X + Math.Sin(arad) * r + MagnifierTip.ActualWidth > this.LayoutGrid.ActualWidth) { arad = -arad; } angle = arad * 180 / Math.PI; } else if (tooHigh) { var dy = -MagnifierTip.MagnifierTranslateTransform.Y; var dx = MagnifierTip.MagnifierTranslateTransform.X + MagnifierTip.ActualWidth - this.LayoutGrid.ActualWidth; var r = MagnifierTip.ActualHeight - MagnifierTip.ActualWidth / 2; var arad1 = -Math.Acos((r - dy) / r); var arad2 = -Math.Asin(dx / r); var arad = Math.Min(arad1, arad2); angle = arad * 180 / Math.PI; } else //if (tooRight) { var dx = MagnifierTip.MagnifierTranslateTransform.X + MagnifierTip.ActualWidth - this.LayoutGrid.ActualWidth; var r = MagnifierTip.ActualHeight - MagnifierTip.ActualWidth / 2; var arad = -Math.Asin(dx / r); angle = arad * 180 / Math.PI; } MagnifierTip.RotateTransform.Angle = angle; MagnifierTip.LensRotateTransform.Angle = -angle; } else { MagnifierTip.RotateTransform.Angle = 0; MagnifierTip.LensRotateTransform.Angle = 0; } } private void CalculateImageScaleAndOffsets(BitmapImage bi, out double offsetX, out double offsetY, out double imageScale) { var imageRatio = (double)bi.PixelWidth / bi.PixelHeight; var gridRatio = this.LayoutGrid.ActualWidth / this.LayoutGrid.ActualHeight; if (bi.PixelWidth < this.LayoutGrid.ActualWidth && bi.PixelHeight < this.LayoutGrid.ActualHeight) { offsetX = 0.5 * (this.LayoutGrid.ActualWidth - bi.PixelWidth); offsetY = 0.5 * (this.LayoutGrid.ActualHeight - bi.PixelHeight); imageScale = 1; } else if (imageRatio < gridRatio) { offsetX = 0.5 * (this.LayoutGrid.ActualWidth - imageRatio * this.LayoutGrid.ActualHeight); offsetY = 0; imageScale = BigImage.ActualHeight / bi.PixelHeight; } else { offsetX = 0; offsetY = 0.5 * (this.LayoutGrid.ActualHeight - this.LayoutGrid.ActualWidth / imageRatio); imageScale = BigImage.ActualWidth / bi.PixelWidth; } } } } 

Loupe.xaml

                              

Le correctif pour 1 ici est de mettre à jour la loupe même lorsque

 LayoutGrid_OnPointerPressed 

Donc, la méthode mise à jour ressemble à

  private void LayoutGrid_OnPointerPressed(object sender, PointerRoutedEventArgs e) { MagnifierTip.Visibility = Windows.UI.Xaml.Visibility.Visible; var point = e.GetCurrentPoint(this.LayoutGrid); this.pointerX = point.Position.X; this.pointerY = point.Position.Y; this.UpdateMagnifier(); } 

Cela vous donne le comportement souhaité dont vous parlez.

Pour résoudre le problème des limites

calculer les valeurs de pointeur ci-dessus par rapport à BitImage au lieu de LayoutGrid.

if (this.pointerX <0.0 || this.pointerY <0.0) return; if (this.pointerX> BigImage.ActualWidth || this.pointerY> BigImage.ActualHeight) return; var bi = (BitmapImage) BigImage.Source;

La rotation lorsque vous approchez du bord consiste à calculer soigneusement l’angle de rotation lorsqu’il atteint le bord et à appliquer cette transformation de Rotation.

 MagnifierTip.RenderTransform = new RotateTransform{Angle=, CenterX=, CenterY=}; 

J’espère que cela t’aides.