WPF图像平移缩放

图像比例关系及缩放规则

<Image Name="image" Source="F:\chenggeng\source\Image\Desert.jpg"
                 Width="Auto" Height="Auto" RenderTransform="{StaticResource Imageview}" Stretch="Uniform"  RenderOptions.BitmapScalingMode="NearestNeighbor"/>

当Stretch="Uniform"时,图像按比例适应布局,在无缩放及平移时,图像中心与布局中心重合。
在这里插入图片描述
如上图的图1与图2所示,布局缩放后会改变布局控件及图像控件的尺寸,但当缩放为1,偏移为0时,黑色框代表的图像与蓝色框代表的区域中心重合在一起。图3为缩放偏移后的位置关系,绿色框代表缩放无偏移后的图像,黑色框代表无缩放无偏移图像,无偏缩放时,图像左上角的位置不变。图四则有如下关系:
有 向 线 段 1 + 有 向 线 段 3 = 有 向 线 段 2 + 有 向 线 段 4 m o v e 1. x + p o i n t . x ∗ s c a l e 1 = m o v e 2. x + p o i n t . x ∗ s c a l e 2 m o v e 2. x − m o v e 1. x = − p o i n t . x ∗ ( s c a l e 2 − s c a l e 1 ) = − p o i n t . x ∗ d e l t a m o v e = m o v e − p o i n t ∗ d e l t a 有向线段1+有向线段3 = 有向线段2+有向线段4 \\ move1.x+point.x*scale1 = move2.x+point.x*scale2 \\ move2.x - move1.x = -point.x*(scale2-scale1) = -point.x*delta \\ move = move - point*delta 线1+线3=线2+线4move1.x+point.xscale1=move2.x+point.xscale2move2.xmove1.x=point.x(scale2scale1)=point.xdeltamove=movepointdelta
即,在滚轮滚动缩放时,使move = move - point*delta即可实现以point为中心的缩放。

根据图3的示意图,绿色图像平移不完全超出蓝色窗口的边界限制条件为:

线段1<move<线段2

W+w > 2*move_x > -((2*scale-1)*w + W)  水平平移限制条件
H+h > 2*move_y > -((2*scale-1)*h + H)  垂直平移限制条件

根据上述结论,前后端代码如下:

PageCamera.xaml:

<Page ...>
  <Grid>
    ...
    <Grid Name="workspace" Grid.Row="2" Grid.Column="1" Background="Black">
      <Grid.Resources>
        <TransformGroup x:Key="Imageview">
          <ScaleTransform/>
          <TranslateTransform/>
        </TransformGroup>
      </Grid.Resources>
      <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled"
                    Cursor="SizeAll" Focusable="False" x:Name="BackFrame">
        <ContentControl MouseLeftButtonDown="ImgMouseLeftButtonDown" 
                        MouseLeftButtonUp="ImgMouseLeftButtonUp"
                        MouseMove="ImgMouseMove"
                        MouseWheel="ImgMouseWheel">
          <Image Name="image" Source="F:\chenggeng\source\Image\Desert.jpg"
                 Width="Auto" Height="Auto" RenderTransform="{StaticResource Imageview}" 
                 Stretch="Uniform"  RenderOptions.BitmapScalingMode="NearestNeighbor"/>
        </ContentControl>
      </ScrollViewer>
    </Grid>
  </Grid>
</Page>

PageCamera.xaml.cs:

...
namespace wpfbase
{
  public partial class PageCamera : Page
  {
    public PageCamera()
    {
      InitializeComponent();
      this.SizeChanged += new System.Windows.SizeChangedEventHandler(PageCameraResized);
    }
    /* -----------窗口大小变化响应------------ */
    private void PageCameraResized(object sender, System.EventArgs e) {
      var group = workspace.FindResource("Imageview") as TransformGroup;
      var scale = group.Children[0] as ScaleTransform;
      var move = group.Children[1] as TranslateTransform;
      move.X = 0;
      move.Y = 0;
      scale.ScaleX = 1;
      scale.ScaleY = 1;
    }
    /* -------------图像缩放处理--------------- */
    // img为可视区域,image为图像
    private bool mouseDown;
    private Point position;
    private void ImgMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
      var img = sender as ContentControl;
      if(img == null) {return;}
      img.CaptureMouse();
      mouseDown = true;
      position = e.GetPosition(img);
  }
    private void ImgMouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
      var img = sender as ContentControl;
      if(img == null) {return;}
      img.ReleaseMouseCapture();
      mouseDown = false;
      var group = workspace.FindResource("Imageview") as TransformGroup;
      var move = group.Children[1] as TranslateTransform;
    }
    private void ImgMouseMove(object sender, MouseEventArgs e) {
      var img = sender as ContentControl;
      if(img == null) {return;}
      if(mouseDown) {
        DoMouseMove(img, e);
      }
    }
    private void DoMouseMove(ContentControl img, MouseEventArgs e) {
      if(e.LeftButton != MouseButtonState.Pressed) {return;}
      var group = workspace.FindResource("Imageview") as TransformGroup;
      var scale = group.Children[0] as ScaleTransform;
      var move = group.Children[1] as TranslateTransform;
      var mouseXY = e.GetPosition(img);
      move.X += mouseXY.X - position.X;
      move.Y += mouseXY.Y - position.Y;
      position = mouseXY;
      // W+w > 2*move_x > -((2*scale-1)*w + W)  水平平移限制条件
      // H+h > 2*move_y > -((2*scale-1)*h + H)  垂直平移限制条件
      if(move.X*2 > image.ActualWidth+img.ActualWidth-20)
        move.X = (image.ActualWidth+img.ActualWidth-20)/2;
      if(-move.X*2 > (2*scale.ScaleX-1)*image.ActualWidth+img.ActualWidth-20)
        move.X = -((scale.ScaleX-0.5)*image.ActualWidth+img.ActualWidth/2-10);
      if(move.Y*2 > image.ActualHeight+img.ActualHeight-20)
        move.Y = (image.ActualHeight+img.ActualHeight-20)/2;
      if(-move.Y*2 > (2*scale.ScaleY-1)*image.ActualHeight+img.ActualHeight-20)
        move.Y = -((scale.ScaleY-0.5)*image.ActualHeight+img.ActualHeight/2-10);
    }
    private void ImgMouseWheel(object sender, MouseWheelEventArgs e) {
      var img = sender as ContentControl;
      if(img == null) {return;}
      var point = e.GetPosition(image);
      var group = workspace.FindResource("Imageview") as TransformGroup;
      var delta = e.Delta * 0.002;
      DoWheelZoom(group, point, delta);
    }
    private void DoWheelZoom(TransformGroup group, Point point, double delta) {
      var transform = group.Children[0] as ScaleTransform;
      if (transform.ScaleX + delta < 0.1) return;
      transform.ScaleX += delta;
      transform.ScaleY += delta;
      var transform1 = group.Children[1] as TranslateTransform;
      transform1.X -= point.X*delta;
      transform1.Y -= point.Y*delta;
    }
  }
}

效果图如下:

wpf图像缩放

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值