在以前的文章使用WPF Resource以及Transform等技术实现鼠标控制图片缩放和移动的效果里面,介绍了如何在WPF里面移动和放大缩小图片,程序也支持使用滚轮的方式缩放图片。然而前面文章里介绍的缩放功能只能以图片中心为原点来实现,但是这种功能往往并不是客户想要的,我们看图片的时候,往往都喜欢以鼠标放在图片的焦点为原点进行图片的缩放。

咋看起来,实现这个功能也不是很难, ScaleTransform类里面定义了CenterX和CenterY两个属性就是用来设置缩放的原点坐标的。将这两个属性分别赋予鼠标的X, Y坐标值,就可以实现对原始图片,以鼠标位置为原点缩放图片了。但是,请注意,我说的原始图片是指没有移动之前的图片,如果图片缩放并且移动了,再次缩放的时候,就是另外一个故事了。

画个图说明一下吧,比如下图里面右下方方块是一个WPF程序里面的一个图片,大小是40 x 40,里面的黑点是预备缩放的原点,假设黑点的坐标是(10, 10),在运行程序的时候,用户首先将方块移动到左边的位置,当然原点(黑点)也移动了,假如这个时候图片移动了50个像素。

接着用户在移动后的位置上,将图片缩放,比如说放大了2倍,这个操作也会移动原点(黑点)在最终图片的位置。因为放大图片,实际上就是将原始图片的各个像素移动到新的位置(红点),这个时候,新的原点(红点)的坐标应该是(20, 20),相邻两个像素的空间使用插值的方法填充。这个时候,

ScaleTransform.ScaleX = 2;

ScaleTransform.ScaleY = 2;

这个时候,用户打算放大图片当中的另外一个区域,再放大一倍(即放大到原图的3倍),下图里是蓝点,假设坐标是(50, 50),因为无论图片缩放与否,用户只会以他在实际图片看到的内容来判断新的缩放焦点:

如果我们直接盲目地将ScaleTransform的各个属性设置为类似下面的值的话:

ScaleTransform.ScaleX = 3;

ScaleTransform.ScaleY = 3;

ScaleTransform.CenterX = 50;

ScaleTransform.CenterY = 50;

就发生问题了, 因为ScaleX = 3表示新图是原图的3倍,然而我们的原点却是在2倍图片上设置的—原图的大小只有40 x 40。解决方案当然是将蓝点的位置转换回在原始图片的位置,注意原始图片应该是下图右下方的图片,而不是左边的—用户最初已经移动了图片。

看起来转换起来有点麻烦,不过WPF提供了一个 函数TransformGroup.Inverse,可以把转换后图片上的坐标转换会在原始图片的坐标。当然啦,如果你熟悉图形学和线性代数的话,实际上,图片的缩放和移动就是将原始图片乘上一个矩阵,而TransformGroup.Inverse函数就是执行矩阵求逆操作。

下面就是关键代码:

XAML代码:

<Grid.Resources>

<TransformGroup x:Key="ImageCompareResources">

<ScaleTransform />

<TranslateTransform/>

</TransformGroup>

</Grid.Resources>

<ScrollViewer HorizontalScrollBarVisibility="Disabled"

VerticalScrollBarVisibility="Disabled" Grid.Row="0" Grid.Column="0"x:Name="MasterScrollViewer" Margin="5" Background="WhiteSmoke">

<ContentControl x:Name="TestContentControl1"

MouseLeftButtonDown="MasterImage_MouseLeftButtonDown"

MouseLeftButtonUp="MasterImage_MouseLeftButtonUp"

MouseMove="MasterImage_MouseMove"

MouseWheel="MasterImage_MouseWheel">

<ImageRenderOptions.BitmapScalingMode="NearestNeighbor"

x:Name="MasterImage" Source="{Binding Path=MasterImagePath}" Stretch="Uniform"

RenderTransform="{StaticResource ImageCompareResources}"/>

</ContentControl>

</ScrollViewer>

C#代码:

private void MasterImage_MouseWheel(object sender, MouseWheelEventArgs e)

{

ContentControl image = sender as ContentControl;

if (image == null)

{

return;

}

TransformGroup group = ImageComparePanel.FindResource("ImageCompareResources") asTransformGroup;

Debug.Assert(group != null, "Can't find transform group from image compare panel resource");

Point point = e.GetPosition(image);

double scale = e.Delta * 0.001;

ZoomImage(group, point, scale);

}

private static void ZoomImage(TransformGroup group, Point point, double scale)

{

Debug.Assert(group != null, "Oops, ImageCompareResources is removed from current control's resouce");

Point pointToContent = group.Inverse.Transform(point);

ScaleTransform transform = group.Children[0] as ScaleTransform;

if (transform.ScaleX + scale < 1)

{

return;

}

transform.ScaleX += scale;

transform.ScaleY += scale;

TranslateTransform transform1 = group.Children[1] as TranslateTransform;

transform1.X = -1 * ((pointToContent.X * transform.ScaleX) - point.X);

transform1.Y = -1 * ((pointToContent.Y * transform.ScaleY) - point.Y);

}

private void MasterImage_MouseMove(object sender, MouseEventArgs e)

{

ContentControl image = sender as ContentControl;

if (image == null)

{

return;

}

if (this.isMouseLeftButtonDown && e.LeftButton == MouseButtonState.Pressed)

{

this.DoImageMove(image, e.GetPosition(image));

}

}

private void DoImageMove(ContentControl image, Point position)

{

TransformGroup group = ImageComparePanel.FindResource("ImageCompareResources") asTransformGroup;

Debug.Assert(group != null, "Can't find transform group from image compare panel resource");

TranslateTransform transform = group.Children[1] as TranslateTransform;

transform.X += position.X - this.previousMousePoint.X;

transform.Y += position.Y - this.previousMousePoint.Y;

this.previousMousePoint = position;

}

本文转自 donjuan 博客园博客,原文链接: http://www.cnblogs.com/killmyday/archive/2009/10/28/1591755.html  ,如需转载请自行联系原作者

http://www.cnblogs.com/killmyday/archive/2009/10/28/1591755.html

在WPF里面实现以鼠标位置为中心缩放移动图片相关推荐

  1. JS-以鼠标位置为中心的滑轮放大功能demo1

    以鼠标位置为中心的滑轮放大功能demo1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &qu ...

  2. 以鼠标位置为中心的图片滚动放大缩小

    1 //以鼠标位置为中心的图片滚动放大缩小 2 $(document).on("mousewheel","#mask img",function(ev){ 3 ...

  3. QT编写实现图片的幻灯片播放、自适应显示、缩放(以鼠标位置为中心进行缩放)、拖动、重置、显示鼠标位置像素坐标及RGB值、播放GIF动画、截图保存、批量保存、拖入文件夹遍历所有文件

    这个图片查看器功能很多,是我花了不少心思,不断优化,不断添加功能的成果: 1.能打开并显示所有常用图片格式文件,显示鼠标位置像素坐标及RGB值 2.能缩放,拖动图片,可以以鼠标为中心滚动滚轮进行缩放 ...

  4. Flash as3 以鼠标点为中心缩放效果

    新建一个元件,名称为pic pic.addEventListener (MouseEvent.MOUSE_WHEEL,zoomHandler); function zoomHandler (e:Mou ...

  5. WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件

    在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件. 例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开. 在这个过程中 ...

  6. js判断鼠标靠近屏幕最侧面的监听_threejs按鼠标位置缩放场景

    threejs的orbitcontrol,默认的缩放模式为整体以target为中心进行缩放.有时候,我们想让场景按照鼠标位置进行缩放,体验起来就和地图的缩放一样,最直观的感觉就是整个场景会越来越靠近鼠 ...

  7. [MFC]OnMouseMove移动位置和OnMouseWheel缩放实现

    (参考:http://baike.baidu.com/view/3036069.htm,http://technet.microsoft.com/zh-cn/library/aa249914) Owe ...

  8. Unity实现以鼠标为中心缩放物体(一)

    Unity实现以鼠标为中心缩放物体(一) 方法一:UGUI下动态设置Pivot Canvas.renderMode = ScreenSpaceCamera Canvas.renderMode = Sc ...

  9. WPF中对鼠标事件转换为命令处理模式的鼠标位置参数传递及EventArgs传递

    在WPF中使用命令模型,对于实现ICommandSource的元素来讲,比较方便,对于未实现ICommandSouce的元素来讲可以利用Blend中提供的行为来解决.通常情况下,命令对象可以传递命令参 ...

  10. WPF 程序鼠标在窗口之外的时候,控件拿到的鼠标位置在哪里?

    在 WPF 程序中,我们有 Mouse.GetPosition(IInputElement relativeTo) 方法可以拿到鼠标当前相对于某个 WPF 控件的位置,也可以通过在 MouseMove ...

最新文章

  1. LeetCode简单题之移动零
  2. jmeter异步请求测试怎么测试_JMeter接口测试之HTTP请求默认值
  3. 这才是真的码“农”!Linux基金会要推广开源技术种菜了
  4. zabbix 3.2安装部署(一)
  5. 通俗介绍拉普拉斯变换,傅里叶变换和z变换
  6. 计算机二级python用什么书-计算机二级 Python 怎么考?考什么?
  7. php 废弃,PHP 7 废弃特性
  8. Python可以这样学(第一季:Python内功修炼)-董付国-专题视频课程
  9. linux安装python3.5_linux安装python3.5.1
  10. AMBA interconnector PL301(一)
  11. sqlserver的like '%xxx%'优化,全文索引
  12. c盘哪些文件可以删除_原来C盘可以删除这5个文件,难怪你的电脑越来越卡
  13. 教务管理系统设计与实现
  14. 微信渐变国旗头像来了!一键生成
  15. 蓝桥杯校赛第十二届第二期模拟赛 c语言
  16. HTML5七夕情人节表白网页制作【花瓣图片表白】HTML+CSS+JavaScript html生日快乐祝福网页制作
  17. 随手笔记Cookie
  18. 2022 互联网中秋月饼大赏,腾讯送火腿,字节寓意圆满,你最钟爱哪款呢?
  19. 微信小程序图片处理方案,解决加载缓慢,影响用户体验
  20. 最优化八:高斯牛顿法、LM法

热门文章

  1. Atitit tomcat 启动报错 ZipException: archive is not a ZIP archive. 1.1. ----Should sh lib jar err... 1
  2. Atitit 软件项目系统托盘图标解决方案
  3. atitit.为什么java体系开发效率这样低的原因and解决
  4. paip.提升效率--数据绑定到table原理和流程Angular js jquery实现
  5. 软件的黑盒和白盒分析方法
  6. BCG全球资产管理报告:行业增长的驱动力
  7. Julia : 小s与关于绝对路径的转义方式
  8. 阿里云存储:安防行业背后的赋能者 | 凌云时刻
  9. 【优化算法】饥饿游戏搜索算法(HGS)【含Matlab源码 1802期】
  10. 【三维路径规划】基于matlab RRT_Star算法三维路径规划【含Matlab源码 1571期】