分享WindowsPhone8系统中缩放图片控件的实现

来源:互联网 发布:nginx rewrite https 编辑:程序博客网 时间:2024/06/06 18:25

         xaml中添加:

<ViewportControl x:Name="viewport" DoubleTap="OnDoubleTap"    ManipulationStarted="OnManipulationStarted" ManipulationDelta="OnManipulationDelta"           ManipulationCompleted="OnManipulationCompleted" ViewportChanged="viewport_ViewportChanged">  <Canvas x:Name="canvas">    <Image x:Name="image"           RenderTransformOrigin="0,0" CacheMode="BitmapCache"          ImageOpened="OnImageOpened">      <Image.RenderTransform>        <ScaleTransform x:Name="xform"/>      </Image.RenderTransform>    </Image>  </Canvas></ViewportControl>

  cs中添加:

namespace ImageExtend{  public partial class ZoomImage : UserControl  {    public static readonly DependencyProperty SourceProperty      = DependencyProperty.Register("Source", typeof(ImageSource), typeof(ZoomImage), new PropertyMetadata(OnImageSourceChanged));    private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)    {      if (d != null && d is ZoomImage)      {        (d as ZoomImage).SetImage((ImageSource)e.NewValue);      }    }    public ImageSource Source    {      get      {        return (ImageSource)GetValue(SourceProperty);      }      set      {        SetValue(SourceProperty, value);      }    }     const double MaxScale = 10;     double _scale = 1.0;    double _minScale;    double _coercedScale;    double _originalScale;     Size _viewportSize;    bool _pinching;    Point _screenMidpoint;    Point _relativeMidpoint;     BitmapImage _bitmap;     public ZoomImage()    {      InitializeComponent();      this.Loaded += ZoomImage_Loaded;    }     void ZoomImage_Loaded(object sender, RoutedEventArgs e)    {      if (Source != null)      {        SetImage(Source);      }    }     void SetImage(ImageSource img)    {      image.Source = img;    }     /// <summary>     /// Either the user has manipulated the image or the size of the viewport has changed. We only     /// care about the size.     /// </summary>     void viewport_ViewportChanged(object sender, System.Windows.Controls.Primitives.ViewportChangedEventArgs e)    {      Size newSize = new Size(viewport.Viewport.Width, viewport.Viewport.Height);      if (newSize != _viewportSize)      {        _viewportSize = newSize;        CoerceScale(true);        ResizeImage(false);      }    }     /// <summary>     /// Handler for the ManipulationStarted event. Set initial state in case     /// it becomes a pinch later.     /// </summary>     void OnManipulationStarted(object sender, ManipulationStartedEventArgs e)    {      _pinching = false;      _originalScale = _scale;    }     /// <summary>     /// Handler for the ManipulationDelta event. It may or may not be a pinch. If it is not a     /// pinch, the ViewportControl will take care of it.     /// </summary>     /// <param name="sender"></param>     /// <param name="e"></param>     void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)    {      if (e.PinchManipulation != null)      {        e.Handled = true;         if (!_pinching)        {          _pinching = true;          Point center = e.PinchManipulation.Original.Center;          _relativeMidpoint = new Point(center.X / image.ActualWidth, center.Y / image.ActualHeight);           var xform = image.TransformToVisual(viewport);          _screenMidpoint = xform.Transform(center);        }         _scale = _originalScale * e.PinchManipulation.CumulativeScale;         CoerceScale(false);        ResizeImage(false);      }      else if (_pinching)      {        _pinching = false;        _originalScale = _scale = _coercedScale;      }    }     /// <summary>     /// The manipulation has completed (no touch points anymore) so reset state.     /// </summary>     void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e)    {      _pinching = false;      _scale = _coercedScale;    }     /// <summary>     /// When a new image is opened, set its initial scale.     /// </summary>     void OnImageOpened(object sender, RoutedEventArgs e)    {      _bitmap = (BitmapImage)image.Source;       // Set scale to the minimum, and then save it.       _scale = 0;      CoerceScale(true);      _scale = _coercedScale;       ResizeImage(true);    }     /// <summary>     /// Adjust the size of the image according to the coerced scale factor. Optionally     /// center the image, otherwise, try to keep the original midpoint of the pinch     /// in the same spot on the screen regardless of the scale.     /// </summary>     /// <param name="center"></param>     void ResizeImage(bool center)    {      if (_coercedScale != 0 && _bitmap != null)      {        double newWidth = canvas.Width = Math.Round(_bitmap.PixelWidth * _coercedScale);        double newHeight = canvas.Height = Math.Round(_bitmap.PixelHeight * _coercedScale);         xform.ScaleX = xform.ScaleY = _coercedScale;         viewport.Bounds = new Rect(0, 0, newWidth, newHeight);         if (center)        {          viewport.SetViewportOrigin(            new Point(              Math.Round((newWidth - viewport.ActualWidth) / 2),              Math.Round((newHeight - viewport.ActualHeight) / 2)              ));        }        else        {          Point newImgMid = new Point(newWidth * _relativeMidpoint.X, newHeight * _relativeMidpoint.Y);          Point origin = new Point(newImgMid.X - _screenMidpoint.X, newImgMid.Y - _screenMidpoint.Y);          viewport.SetViewportOrigin(origin);        }      }    }     /// <summary>     /// Coerce the scale into being within the proper range. Optionally compute the constraints     /// on the scale so that it will always fill the entire screen and will never get too big     /// to be contained in a hardware surface.     /// </summary>     /// <param name="recompute">Will recompute the min max scale if true.</param>     void CoerceScale(bool recompute)    {      if (recompute && _bitmap != null && viewport != null)      {        // Calculate the minimum scale to fit the viewport         double minX = viewport.ActualWidth / _bitmap.PixelWidth;        double minY = viewport.ActualHeight / _bitmap.PixelHeight;         _minScale = Math.Min(minX, minY);      }       _coercedScale = Math.Min(MaxScale, Math.Max(_scale, _minScale));     }     private void OnDoubleTap(object sender, GestureEventArgs e)    {      e.Handled = true;       _scale = 0;      CoerceScale(true);      _scale = _coercedScale;       ResizeImage(true);    }  }}
0 0
原创粉丝点击