zoukankan      html  css  js  c++  java
  • 一个Pan&Zoom的Behavior

    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);
    }
    }

  • 相关阅读:
    从一个iOS毛头小子到现在的高级工程师, 我总结了一些经验,先跟大家分享一下一些好的资料
    iOS面试题---Objective_C语言特性:分类、扩展、代理、通知、KVO、KVC、属性
    200道iOS面试题面试题整理,底层、技术亮点公司需要的这里都有
    [iOS 开发] iOS 开发从菜鸟到高手?听听他们怎么说
    2020年面向iOS开发人员的知识点总结(更新中)
    OC项目转Swift指南
    来自老程序员的10条中肯建议
    面对职业瓶颈,iOS 开发人员应该如何突破?
    憨憨程序猿,不要让你的技术被简历埋没了
    总结:实现线程同步的八种方式
  • 原文地址:https://www.cnblogs.com/walleyekneel/p/3133712.html
Copyright © 2011-2022 走看看