WPF 鼠标滚轮对图片的缩放

来源:互联网 发布:淘宝双11如何抢购 编辑:程序博客网 时间:2024/03/29 18:06

一次开发过程中遇到一个需求,需要以鼠标为中心点,利用鼠标滚轮对图片进行缩放。网上的资源还是很多的:
参考了如下一篇文档的缩放算法:尊重作者原创,附原文地址:
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图片缩放效果

原创粉丝点击