简体   繁体   中英

Windows Phone: Can't get ViewportControl to align

I've been trying to implement pinch-and-zoom using the ViewportControl class in a Windows Phone 8 Silverlight app for quite some time without any success. There are some great samples out there, such as this one , but I haven't been able to map the examples that I found to my scenario.

Pinching and zooming works fine, the problem I'm having is with the alignment of the viewport with the content, after the manipulation has completed.

The main problem I'm facing is that after my manipulation has completed, I've been unable to align the scaled content (a XAML canvas and sub tree which is the child of the ViewportControl) to the viewport. This results in the effective bounds of the viewport (the scrollable area) being offset from my content, resulting in part of my content being unreachable/unscrollable.

Here is my algorithm for the manipulation:

  1. Pinch manipulation starts.
  2. Apply render transform to canvas' sub tree during pinch.
  3. Manipulation completes.
  4. Scale main canvas to the effective size of the render-transformed sub tree (this works as expected and the canvas is aligned with the render-transformed sub tree).
  5. Obtain a transform between the canvas inside the ViewportControl and the viewport control itself.
  6. Use the transform to obtain a bounding rect which (I expect) should represent a rect which overlays the content I want to scroll inside the ViewportControl, but in the coordinate space of the hosting ViewportControl.
  7. Apply this rect as the viewport bounds of the ViewportControl.
  8. Set the origin of the viewport to the translated top-left coordinates of the canvas

Here is where I calculate and apply the new bounds, after the manipulation has completed:

 // Obtain transform between canvas and ViewportControl            
 GeneralTransform gt = m_MainCanvas.TransformToVisual(m_ViewportControl);
 Rect newBounds = gt.TransformBounds(new Rect(0, 0, m_MainCanvas.Width, m_MainCanvas.Height));
 m_ViewportControl.Bounds = newBounds;

 // set the origin of the viewport again
 m_ViewportControl.SetViewportOrigin(gt.Transform(new Point(0, 0)));

This is resulting in my content being misaligned with the viewport.

Try, try as I might, I haven't been able to figure out what I'm doing wrong here... even after looking at tutorials that show how to solve this... :|

I figure that what is happening is that my rect that I'm setting the bounds to is sized correctly, but it's X and Y coordinates are off. I was hoping that this would be addressed by using the transform between the canvas and the ViewportControl itself, but apparently not.

Question: How do I go about setting the origin of the ViewportControl correctly (how do I calculate the point to pass to the SetViewportOrigin method? Can someone please explain this ratio that people are using between the scaled contents and the viewport that I see in other examples of how to crack this?

7/8/2014 Update

I made some headway here. My approach of getting a transform between the content in the ViewportControl and the control itself, then using this to obtain a rect in the control's space to use as the bounds for the viewport wasn't working. My workaround was to simply wrap the render-transformed content in a canvas which I resized the effective (render transformed) size. Then I set the bounds to that size and I finally had the nice bounce-back effect working.

The problem I'm facing now is that when I resize the canvas and reset the bounds for the viewport, the content snaps to the top-left corner of the viewport, and is no longer centered around the pinch area that the user provided.

Can anyone help me understand how the SetViewportOrigin method works on ViewportControl? I'm seeing some really odd data for the Viewport vs. the canvas after a pinch manipulation:

Canvas Size = 1025.69, 1641.11
Bounds = 0,0,1025.69,1641.11
viewport = -56,41.00,480,698

Why is the viewport offset with non-zero values (x,y = -56,41) when I don't even call SetViewportOrigin(Point)?

Here is how I'm thinking the SetViewportOrigin(Point) method works: let's say my Viewport control itself was sized to 400 x 400 pixels, and my content was 800 x 800 pixels. If I set the origin of the viewport to 100, 100 the content would be scrolled such that the first 100 vertical and 100 horizontal pixels would be clipped/masked/offscreen. Is this not how the ViewportControl works?

I figured this out and am a happy camper now. It turned out that I was setting the viewport origin to a point using the wrong coordinate space. I was thinking that if I wanted to move the content to a certain place, that I would provide that point in the coordinate space of the viewport and the content would scroll (setting the upper-left point of the content). What I figured out is that the Point data that the SetViewportOrigin method takes is in the coordinate space of the content. For example: if your content is 500 x 500 pixels wide, your viewport is 400 x 400 pixels wide, and you'd like the first 100 vertical and 100 horizontal pixels to be masked by the viewport (showing the bottom-right corner of the content), you would set the origin to be 100,100, not -100,100.

I was doing a bunch of useless conversion between coordinate spaces, trying to pass the viewport a point in its coordinate system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM