@@ -92,10 +92,12 @@ private void OnPaintCanvas(object sender, SKPaintSurfaceEventArgs e)
9292 }
9393
9494
95- float currentScale = 1 ;
96- float startScale = 1 ;
97- SKPoint offsetPosition = new SKPoint ( 0 , 0 ) ;
98- SKPoint translation = new SKPoint ( 0 , 0 ) ;
95+ double zoomCurScale = 1 ;
96+ double zoomStartScale = 1 ;
97+
98+ SKPoint zoomStartOrigin = new SKPoint ( 0 , 0 ) ;
99+ SKPoint zoomStartOffset = new SKPoint ( 0 , 0 ) ;
100+ SKPoint zoomTranslation = new SKPoint ( 0 , 0 ) ;
99101
100102 void OnPinchUpdated ( object sender , PinchGestureUpdatedEventArgs e )
101103 {
@@ -106,51 +108,60 @@ void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
106108 {
107109 // Store the current scale factor applied to the wrapped user interface element,
108110 // and zero the components for the center point of the translate transform.
109- startScale = currentScale ;
111+ zoomStartScale = zoomCurScale = axisChart . XForm . Scale ;
112+ zoomStartOrigin = new SKPoint ( ( float ) e . ScaleOrigin . X , ( float ) e . ScaleOrigin . Y ) ;
113+ zoomStartOffset = axisChart . XForm . Offset ;
110114 }
115+
111116 if ( e . Status == GestureStatus . Running )
112117 {
118+ // e.Scale is the delta to be applied for the current frame
113119 // Calculate the scale factor to be applied.
114- currentScale += ( float ) ( ( e . Scale - 1 ) * startScale ) ;
115- currentScale = Math . Max ( 1 , currentScale ) ;
116- currentScale = Math . Min ( 5 , currentScale ) ;
120+ zoomCurScale += ( e . Scale - 1 ) * zoomStartScale ;
121+ zoomCurScale = Math . Max ( 1 , zoomCurScale ) ;
122+ zoomCurScale = Math . Min ( 5 , zoomCurScale ) ;
123+
124+
125+ SKPoint zoomPanDelta = new SKPoint ( ( float ) ( ( e . ScaleOrigin . X - zoomStartOrigin . X ) * CanvasSize . Width ) , ( float ) ( ( e . ScaleOrigin . Y - zoomStartOrigin . Y ) * CanvasSize . Height ) ) ;
117126
118127 // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
119128 // so get the X pixel coordinate.
120- double renderedX = X + offsetPosition . X ;
129+ double renderedX = X + zoomStartOffset . X ;
121130 double deltaX = renderedX / CanvasSize . Width ;
122- double deltaWidth = CanvasSize . Width / ( CanvasSize . Width * startScale ) ;
131+ double deltaWidth = CanvasSize . Width / ( CanvasSize . Width * zoomStartScale ) ;
123132 double originX = ( e . ScaleOrigin . X - deltaX ) * deltaWidth ;
124133
134+ //Console.WriteLine("ScaleOrigin: {0}, {1}", e.ScaleOrigin.X, e.ScaleOrigin.Y);
135+
125136 // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
126137 // so get the Y pixel coordinate.
127- double renderedY = Y + offsetPosition . Y ;
138+ double renderedY = Y + zoomStartOffset . Y ;
128139 double deltaY = renderedY / CanvasSize . Height ;
129- double deltaHeight = CanvasSize . Height / ( CanvasSize . Height * startScale ) ;
140+ double deltaHeight = CanvasSize . Height / ( CanvasSize . Height * zoomStartScale ) ;
130141 double originY = ( e . ScaleOrigin . Y - deltaY ) * deltaHeight ;
131142
132143 // Calculate the transformed element pixel coordinates.
133- double targetX = offsetPosition . X - ( originX * CanvasSize . Width ) * ( currentScale - startScale ) ;
134- double targetY = offsetPosition . Y - ( originY * CanvasSize . Height ) * ( currentScale - startScale ) ;
144+ double targetX = zoomStartOffset . X - ( originX * CanvasSize . Width ) * ( zoomCurScale - zoomStartScale ) ;
145+ double targetY = zoomStartOffset . Y - ( originY * CanvasSize . Height ) * ( zoomCurScale - zoomStartScale ) ;
135146
136147 // Apply translation based on the change in origin.
137- translation . X = ( float ) targetX . Clamp ( - CanvasSize . Width * ( currentScale - 1 ) , 0 ) ;
138- translation . Y = ( float ) targetY . Clamp ( - CanvasSize . Height * ( currentScale - 1 ) , 0 ) ;
148+ zoomTranslation . X = ( float ) targetX ;
149+ zoomTranslation . Y = ( float ) targetY ;
150+
139151
140- //Console.WriteLine("{0}, {1}", translation.X, translation.Y);
152+ SKPoint final = zoomTranslation + zoomPanDelta ;
153+ final . X = Math . Min ( Math . Max ( final . X , - CanvasSize . Width * ( float ) ( zoomCurScale - 1 ) ) , 0 ) ;
154+ final . Y = Math . Min ( Math . Max ( final . Y , - CanvasSize . Height * ( float ) ( zoomCurScale - 1 ) ) , 0 ) ;
155+
141156
142- axisChart . XForm . Scale = currentScale ;
143- axisChart . XForm . Offset = translation ;
157+ axisChart . XForm . Scale = ( float ) zoomCurScale ;
158+ axisChart . XForm . Offset = final ;
144159 InvalidateSurface ( ) ;
145160
146161 }
162+
147163 if ( e . Status == GestureStatus . Completed )
148164 {
149- // Store the translation delta's of the wrapped user interface element.
150- offsetPosition = translation ;
151-
152- axisChart . XForm . Scale = currentScale ;
153- axisChart . XForm . Offset = translation ;
154165 InvalidateSurface ( ) ;
155166 }
156167 }
0 commit comments