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
scale s
= scale around (s.x,s.y) with factor s.x in x direction and s.y in y direction
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):
translate a . translate b = translate (a+b)
scale a . scale b = scale (a*b)
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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…