WPF 鼠标滚轮对图片的缩放

一次开发过程中遇到一个需求,需要以鼠标为中心点,利用鼠标滚轮对图片进行缩放。网上的资源还是很多的:
参考了如下一篇文档的缩放算法:尊重作者原创,附原文地址:
https://www.cnblogs.com/kongxianghai/archive/2012/06/26/2562966.html
给这篇blog点赞,实现的效果不错!

        private void Window_MouseWheel(object sender, MouseWheelEventArgs e) {
            if (e.Delta == 0) return;


            double d = e.Delta / Math.Abs(e.Delta);
            if (_scaleValue < 0.5 && d < 0) return;

            if (_scaleValue > 20 && d > 0) return;

            _scaleValue += d * .2;

            //获取鼠标在缩放之前的目标上的位置
            Point targetZoomFocus1 = e.GetPosition(target);

            //获取目标在缩放之前的Rect
            //Rect beforeScaleRect =
            //    target.RenderTransform.TransformBounds(new Rect(target.RenderSize));

            //缩放的中心点为左上角(0,0)
            scaler.ScaleX = _scaleValue;
            scaler.ScaleY = _scaleValue;

            //获取鼠标在缩放之后的目标上的位置
            Point targetZoomFocus2 = new Point(targetZoomFocus1.X * (1 + d * .2), targetZoomFocus1.Y * (1 + d * .2));

            //获取目标在缩放之后的Rect
            Rect afterScaleRect = target.RenderTransform.TransformBounds(new Rect(target.RenderSize));

            //算的缩放前后鼠标的位置间的差
            Vector v = targetZoomFocus2 - targetZoomFocus1;


            if (afterScaleRect.Size.Width <= _viewportSize.Width) {
                //缩放之后居中
                double widthHalfDelta = (Container.RenderSize.Width - afterScaleRect.Width) / 2;
                translater.X = widthHalfDelta;
            }
            else if (afterScaleRect.X - v.X > 0) {
                //目标左边界与可视左边界对齐
                translater.X = 0;
            }
            else if (afterScaleRect.X + afterScaleRect.Width - v.X < Container.RenderSize.Width) {
                //目标右边界与可视右边界对齐
                translater.X = Container.RenderSize.Width - afterScaleRect.Size.Width;
            }
            else {
                //减去鼠标点在缩放前后之间的差值,实际上就是以鼠标点为中心进行缩放
                translater.X -= v.X;
            }


            if (afterScaleRect.Size.Height <= _viewportSize.Height) {
                double heightHalfDleta = (Container.RenderSize.Height - afterScaleRect.Height) / 2;
                translater.Y = heightHalfDleta;
            }
            else if (afterScaleRect.Y - v.Y > 0) {
                translater.Y = 0;
            }
            else if (afterScaleRect.Y + afterScaleRect.Height - v.Y < Container.RenderSize.Height) {
                translater.Y = Container.RenderSize.Height - afterScaleRect.Size.Height;
            }
            else {
                translater.Y -= v.Y;
            }

        }

实际在项目运用中用此方法碰见了2个问题:
问题1:缩放时放大的元素脱离了布局,缩放超过了父容器的限制,遮挡了界面中其他的布局,此问题多半是布局造成的bug,调整先后顺序可以解决此问题,

问题2:
//获取鼠标在缩放之后的目标上的位置
Point targetZoomFocus2 = new Point(targetZoomFocus1.X * (1 + d * .2), targetZoomFocus1.Y * (1 + d * .2));
bug发现 targetZoomFocus2 的x,y 坐标永远是(0,0)
解决此问题的办法是:

 _scaleValue += d * .2;
            Point targetZoomFocus1 = e.GetPosition(this);
            //ScaleTransform scaler = new ScaleTransform(_scaleValue,_scaleValue,0,0);
            Matrix mt = translater.Value;
            mt.M11 = _scaleValue;
            mt.M22 = _scaleValue;
            this.RenderTransform.Matrix = mt;

bug出现前的代码为:

  _scaleValue += d * .2;
            Point targetZoomFocus1 = e.GetPosition(this);
            ScaleTransform scaler = new ScaleTransform(_scaleValue,_scaleValue,0,0);

            **this.RenderTransform.Matrix = scaler.Value;**
            Point targetZoomFocus2 = new Point(targetZoomFocus1.X * (1 + d * .2), targetZoomFocus1.Y * (1 + d * .2));
            //Point pt=  (this.Parent as Canvas).TransformToAncestor(App.Current.MainWindow).Transform(new Point(0, 0));
            Rect afterScaleRect = this.RenderTransform.TransformBounds(new Rect(this.RenderSize));

即在缩放前需要对平移变化也要赋值,具体问题本质还不是特别清楚,但问题经过调试,通过对代码改进解决了缩放的问题。记录于此,供日后参阅方便!
bugFix图片缩放效果

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值