Pan&Zoom是个很常用的操作,但是不想每次都去重新写各种GerstureListener事件,所以就参考这篇,改写了个简单的Behavior。
public class ZoomAndPanBehavior2 : Behavior<Image>
{ private Image _currentImage { get { return AssociatedObject as Image; } } private PhoneApplicationPage _currentPage{ get{ var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;var currentPage = rootFrame.Content as PhoneApplicationPage;return currentPage;}} private GestureListener _gl { get { return GestureService.GetGestureListener(_currentImage); } } private double _totalImageScale = 1d;private Point _imagePosition = new Point(0, 0); private Point _oldFinger1;private Point _oldFinger2;private double _oldScaleFactor; //旧的缩放因子 private CompositeTransform _compositeTransfrom;private MatrixTransform _previousTransform;private TransformGroup _transfromGruop;private TransformGroup _currentGroup; bool isDragging;bool isPinching;Point ptPinchPositionStart; protected override void OnAttached(){ base.OnAttached();_compositeTransfrom = new CompositeTransform();_previousTransform = new MatrixTransform { Matrix = Matrix.Identity };_transfromGruop = new TransformGroup();_currentGroup = new TransformGroup();_currentGroup.Children.Add(_compositeTransfrom);_transfromGruop.Children.Add(_currentGroup);_transfromGruop.Children.Add(_previousTransform);_currentImage.RenderTransform = _transfromGruop;_currentImage.RenderTransformOrigin = new Point(0, 0);_gl.DragStarted += _gl_DragStarted;_gl.DragDelta += _gl_DragDelta;_gl.PinchStarted += _gl_PinchStarted;_gl.PinchDelta += _gl_PinchDelta;_gl.PinchCompleted += _gl_PinchCompleted;_gl.Hold += _gl_Hold;_gl.DoubleTap += _gl_DoubleTap;} protected override void OnDetaching(){ base.OnDetaching();_gl.DragStarted -= _gl_DragStarted;_gl.DragDelta -= _gl_DragDelta;_gl.PinchStarted -= _gl_PinchStarted;_gl.PinchDelta -= _gl_PinchDelta;_gl.PinchCompleted -= _gl_PinchCompleted;_gl.Hold -= _gl_Hold;_gl.DoubleTap -= _gl_DoubleTap;_compositeTransfrom = null;} void _gl_DoubleTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e){ Point imageCenter = e.GetPosition(_currentImage);if (_compositeTransfrom.ScaleX != 2)_compositeTransfrom.ScaleY = _compositeTransfrom.ScaleX = 2;else_compositeTransfrom.ScaleX = _compositeTransfrom.ScaleY = 1;_compositeTransfrom.CenterX = imageCenter.X;_compositeTransfrom.CenterY = imageCenter.Y;} void _gl_Hold(object sender, Microsoft.Phone.Controls.GestureEventArgs e){ } void _gl_PinchStarted(object sender, PinchStartedGestureEventArgs e){ _oldFinger1 = e.GetPosition(_currentImage, 0);_oldFinger2 = e.GetPosition(_currentImage, 1);_oldScaleFactor = 1;isPinching = true;}void _gl_PinchDelta(object sender, PinchGestureEventArgs e){ //DistanceRatio表示缩放之后手指之间的距离与缩放前手指之间距离的比例var scaleFactor = e.DistanceRatio / _oldScaleFactor; var currentFinger1 = e.GetPosition(_currentImage, 0);var currentFinger2 = e.GetPosition(_currentImage, 1); Point tranlationDelta;tranlationDelta = GetTranslationDelta(currentFinger1, currentFinger2, _oldFinger1, _oldFinger2, _imagePosition, scaleFactor); _oldFinger1 = currentFinger1;_oldFinger2 = currentFinger2;_oldScaleFactor = e.DistanceRatio;UpdateImage(scaleFactor, tranlationDelta);} void _gl_PinchCompleted(object sender, PinchGestureEventArgs e){ isPinching = false;} void _gl_DragStarted(object sender, DragStartedGestureEventArgs e){ } void _gl_DragDelta(object sender, DragDeltaGestureEventArgs e){ if (isPinching)return;if (_totalImageScale > 1 || _compositeTransfrom.ScaleX > 1){ _compositeTransfrom.TranslateX += e.HorizontalChange;_compositeTransfrom.TranslateY += e.VerticalChange;}} private void UpdateImage(double scaleFactor, Point delta){ _totalImageScale *= scaleFactor;_imagePosition = new Point(_imagePosition.X + delta.X, _imagePosition.Y + delta.Y); if (_totalImageScale > 1){ _compositeTransfrom.ScaleX = _totalImageScale;_compositeTransfrom.ScaleY = _totalImageScale;_compositeTransfrom.TranslateX = _imagePosition.X;_compositeTransfrom.TranslateY = _imagePosition.Y;}else{ _compositeTransfrom.ScaleX = _compositeTransfrom.ScaleY = 1;_compositeTransfrom.TranslateX = _compositeTransfrom.TranslateY = 0;_imagePosition = new Point(0, 0);}} private Point GetTranslationDelta(Point currentFinger1, Point currentFinger2, Point oldFinger1,Point oldFinger2, Point currentPosition, double scaleFactor){ var newPos1 = new Point(currentFinger1.X + (currentPosition.X - oldFinger1.X) * scaleFactor,currentFinger1.Y + (currentPosition.Y - oldFinger1.Y) * scaleFactor); var newPos2 = new Point(currentFinger2.X + (currentPosition.X - oldFinger2.X) * scaleFactor,currentFinger2.Y + (currentPosition.Y - oldFinger2.Y) * scaleFactor); var newPos = new Point((newPos1.X + newPos2.X) / 2,(newPos1.Y + newPos2.Y) / 2); return new Point(newPos.X - currentPosition.X,newPos.Y - currentPosition.Y);}}