Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
242 views
in Technique[技术] by (71.8m points)

c# - Smooth pinch-zooming and panning on Windows Phone 8

I've managed to implement pinch zooming and panning by hooking up to the ManipulationDelta and ManipulationStarted events (on an image control):

    private void image_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        var transform = (CompositeTransform)image.RenderTransform;

        // pan
        transform.TranslateX = _translationX + e.CumulativeManipulation.Translation.X;
        transform.TranslateY = _translationY + e.CumulativeManipulation.Translation.Y;

        // zoom
        if (e.PinchManipulation != null)
        {
            transform.CenterX = e.PinchManipulation.Original.Center.X;
            transform.CenterY = e.PinchManipulation.Original.Center.Y;

            transform.ScaleX = _scaleX * e.PinchManipulation.CumulativeScale;
            transform.ScaleY = _scaleY * e.PinchManipulation.CumulativeScale;
        }
    }

    private void image_OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
    {
        // the user has started manipulating the screen, set starting points
        var transform = (CompositeTransform)image.RenderTransform;
        _scaleX = transform.ScaleX;
        _scaleY = transform.ScaleY;
        _translationX = transform.TranslateX;
        _translationY = transform.TranslateY;
    }

But the compared to the smoothness of the rest of the windows phone UI it feels very placid and stiff. There is no inertia in the movement.

Is there a way to make the movements more smooth? Is using animations and storyboards a way to go about it? I've tried using ScrollView for at least getting smooth panning but then the ManipulationDelta events are not firing correctly.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I wanted to get this right from a mathematical point of view. The result is something similar in correctness to Telerik's PanAndZoomImage. If you aren't interested, jump straight to this gist (It works with WP7.1+). You'll need to reference System.Windows.Interactivity and the Windows Phone toolkit.

Usage:

<Image Source="http://i.imgur.com/ZbKlRzK.jpg">
    <i:Interaction.Behaviors>
        <phoneApp1:PanAndZoomBehavior MaxZoom="10" />
    </i:Interaction.Behaviors>
</Image>

Math

Panning and zooming uses 2 out of 4 transformations of CompositeTransform, namely Translation and Scaling. The key point is understanding how to compose two of those scale+translate transforms. I'll use haskellish notation, because it is less of burden to type and read. Our 'primitives' are

  1. scale s = scale around (s.x,s.y) with factor s.x in x direction and s.y in y direction
  2. translate t = offset all points by t.x in x direction and t.y in y direction

CompositeTransform scales around a center point, which is expressed like

scaleAround c s = translate c . scale s . translate -c

The following rules hold (do the math if you don't believe me, all operators are componentwise):

  1. translate a . translate b = translate (a+b)
  2. scale a . scale b = scale (a*b)
  3. translate t . scale s = scale s . translate (t/s)

A CompositeTransform is like

transform s c t = translate t . scaleAround c s
                = translate (t+c) . scale s . translate -c

When composing two of those transforms, we have to move around primitives until we get to such a form above. Let a and b be those two CompositeTransforms. So we get:

transform' = b . a
           = translate bt . scaleAround bc bs . translate at . scaleAround ac as
           = translate bt . translate bc . scale bs . translate -bc . translate at . translate ac . scale as . translate -ac
           = translate (bt+bc) . scale bs . translate (ac+at-bc) . scale as . translate -ac
           = translate (bt+bc) . translate (ac+at-bc)*bs . scale bs . scale as . translate -ac
           = translate (bt+bc+(ac+at-bc)*bs) . scale (as*bs) . translate -ac
           = translate (bt+bc-ac+(ac+at-bc)*bs) . scaleAround ac (as*bs)
           = translate (bt+at*bs+(bs-1)*(ac-bs)) . scaleAround ac (as*bs)

This is just because I was frustrated with the amount of profound documentation on why certain people do certain things.

For the actual composition code, looko here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...