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
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.
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.
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.