WPF图片预览之移动、旋转、缩放

本文介绍了如何在WPF中实现图片预览功能,包括移动、旋转和缩放操作。利用Zoombox控件或自定义代码实现,通过MouseMove、MouseWheel事件触发操作。在缩放时,限制最小缩放系数为0.3。在移动过程中,需要注意图片移动范围的限制,避免图片移出窗口。同时,讨论了旋转操作中坐标转换的细节,确保旋转后仍能正确移动图片。
摘要由CSDN通过智能技术生成

RT,这个功能比较常见,但凡涉及到图片预览的都跑不了,在说自己的实现方式前,介绍一个好用的控件:Extended.Toolkit中的Zoombox,感兴趣的同学可以去搜一下这个控件,它封装了常用的预览功能。

开始撸代码,整理一下思路先:
首先打算用一个Window来展示图片,但是QQ、微信预览图片的时候,任务栏并没有出现图标,难道用了什么黑科技?不管它,将Window的ShowInTaskbar设置为False就可以不显示在任务栏了。
继续,提到移动、旋转、缩放之类的,WPF提供了与之对应的Transform:TranslateTransform、RotateTransform、ScaleTransform,所以我们必然要使用他们仨了。怎么触发呢?那就用到事件了,移动么MouseMove,缩放么MouseWheel,旋转的话就是固定的按钮的点击事件了。另外,缩放的话可以限制一下最大和最小的缩放系数,我这边只设了缩小时如果小于系数0.3就不再缩小了,放大系数没有设置。

说一下其中的坑:
MouseWheel事件参数里会取到鼠标的Delta,这个参数不好直接用来设置缩放系数,那多少合适呢,看到别人的经验之谈,用这个Delta/3000即可。

double delta = (double)e.Delta / 3000;
ScaleTransform scale = group.Children[0] as ScaleTransform;
if (scale.ScaleX < 0.3 && scale.ScaleY < 0.3 && e.Delta < 0)
{
        return;
}
scale.CenterX = this.imageControl.ActualWidth / 2;
scale.CenterY = this.imageControl.ActualHeight / 2;
scale.ScaleX += delta;
scale.ScaleY += delta;

MouseMove移动图片的时候,是可以将整个图片移到Window外面去的,这就要我们限制一下图片的移动范围了:

   private void TopMove(TranslateTransform translate, Point position, Point imagePos) 
        {
            if (scaleValue > 1.0)
            {
                if (mouseXY.Y - position.Y > 0.0)//up
                {
                    double wm = winHeight - position.Y;
                    double im = (this.imageControl.ActualHeight - imagePos.Y) * scaleValue;
                    if (wm - im <= -5.0)
                    {
                        translate.Y -= mouseXY.Y - position.Y;
                    }
                }
                else
                {
                    if (position.Y / scaleValue - imagePos.Y <= -5.0)
                    {
                        translate.Y -= mouseXY.Y - position.Y;
                    }
                }
                if (mouseXY.X - position.X > 0.0)//left
                {
                    double iw = (this.imageControl.ActualWidth - imagePos.X) * scaleValue;
                    double ww = winWidth - position.X;
                    if (ww - iw <= -5.0)
                    {
                        translate.X -= mouseXY.X - position.X;
                    }
                }
                else
                {
                    if (position.X / scaleValue - imagePos.X <= -5.0)
                    {
                        translate.X -= mouseXY.X - position.X;
                    }
                }
            }
            else
            {
                if (mouseXY.Y - position.Y > 0.0)//up
                {
                    if (position.Y / scaleValue >= imagePos.Y)
                    {
                        translate.Y -= mouseXY.Y - position.Y;
                    }
                }
                else
                {
                    double im = (this.imageControl.ActualHeight - imagePos.Y) * scaleValue;
                    double wm = winHeight - position.Y;
                    if (im <= wm)
                    {
                        translate.Y -= mouseXY.Y - position.Y;
                    }
                }
                if (mouseXY.X - position.X > 0.0)//left
                {
                    if (position.X / scaleValue >= imagePos.X)
                    {
                        translate.X -= mouseXY.X - position.X;
                    }
                }
                else
                {
                    double iw = (this.imageControl.ActualWidth - imagePos.X) * scaleValue;
                    double ww = winWidth - position.X;
                    if (iw <= ww)
                    {
                        translate.X -= mouseXY.X - position.X;
                    }
                }
            }
        }

稍微解释一下上面的代码,position是鼠标相对于Window的位置,imagePos是鼠标相对于图片的位置,scaleValue是图片当前的缩放比例,当图片是缩小状态(scaleValue<1)时,允许图片在整个Window里拖动,上移时,如果图片上边框触碰到了Window上边框,则不能再上移(另外3个方向原理相同),反之(scaleValue>1),只有当图片超出Window范围时才允许拖动,假设,图片上下超出了Window,则只能上下移动不能左右移动,并且,上移时,如果图片下边框触碰到了Window下边框,则不能再上移(另外3个方向原理相同)。
眼尖的同学可能注意到了上面这个方法名:TopMove,没错,这个算法只适用于图片正着放的时候的位移计算,我们不是有旋转吗,旋转了只有就不能这么算了,原因在于,imagePos始终是相对于图片来的,也就是说,如果图片旋转了90°,那么imagePos的坐标系也要旋转90°,但是我们最终要计算的是相对于Window的坐标系,所以要做相应的转换。

好了,上完整的代码:

<Window x:Class="VcreditChat.Windows.MaxPicture"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
        WindowStyle="None" 
        AllowsTransparency="True"
        Background="#82000000"
        KeyDown="PicWin_KeyDown"
        Loaded="PicWin_Loaded"
        MouseLeftButtonDown="Window_MouseLeftButtonDown"   
        WindowStartupLocation="CenterScreen"
        Icon="../Resources/Images/ico_48.ico"
        ShowInTaskbar="False"
        Closed="PicWin_Closed"
        x:Name="picWin">
    <Grid x:Name="outGrid">
        <Grid.Resources>
            <TransformGroup x:Key="transGroup">
                <ScaleTransform/>
                <TranslateTransform/>
            
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值