WPF中实现以鼠标为中心的缩放和移动图片或控件对象

前言:因项目中需要用到对图片对象Image控件的放大缩小及移动,且以鼠标为中心点,查了资料,理解后将实现代码记录如下,方便下次使用。

在WPF中要实现控件的缩放和移动,有现成的工具类可以使用,主要是TransformGroup类,ScaleTransform类和TranslateTransform 类。

TransformGroup类是一个组合,下面有一个Children集合,将ScaleTransform和TranslateTransform 丢到集合中,然后将TransformGroup丢给需要缩放平移的控件对象。控件对象如何接收?每个控件都有一个属性叫RenderTransform,专门用来实现控件自身的缩放平移等变换效果。


border.RenderTransform = TransformGroup;//给Border对象设置一个变换组实例

有一个关键点要理解,如果要移动border对象,那么这个border对象是相对于谁而移动?答案是相对于它的父容器。通常我们用Canvas来做父容器。然后在这个Canvas的各种鼠标操作(按下、移动、滑动滚轮、弹起)事件中去实现缩放平移功能。

下面是部分代码说明:

首先是ViewModel部分

private double mouseX = 0;
public double MouseX
{
	get{return mouseX;}
	set{mouseX=value;RaisePropertyChanged();}
}

private double mouseY = 0;
public double MouseY
{
	get{return mouseY;}
	set{mouseY=value;RaisePropertyChanged();}
}

private double delta= 0;
public double Delta
{
	get{return delta;}
	set{delta=value;RaisePropertyChanged();}
}

然后是WPF前端代码部分

<Grid>
	<Grid.RowDefinitions>
		<RowDefinition Height="auto"/>
		<RowDefinition/>
	</Grid.RowDefinitions>
	<StackPanel Grid.Row="0" Orientation="Horizontal">
		<TextBlock Text="{Binding MouseX}" Margin="5"/>
		<TextBlock Text="{Binding MouseY}" Margin="5"/>
		<TextBlock Text="{Binding Delta}" Margin="5"/>
	</StackPanel>
	<Canvas Grid.Row="1" x:Name="canvas" Background="Black" ClipToBounds="True"
			MouseRightButtonDown="Canvas_MouseRightButtonDown"
			MouseRightButtonUp="Canvas_MouseRightButtonUp"
			MouseLeftButtonDown="Canvas_MouseLeftButtonDown"
			MouseLeftButtonUp="Canvas_MouseLeftButtonUp"
			MouseMove="Canvas_MouseMove"
			MouseWheel="Canvas_MouseWheel">
		<Border x:Name="border" Width="200" Height="100" Background="LightCoral">
			<Grid>
				<Border Width="100" Height="100" CornerRadius="100" Background="LightBlue"/>
				<TextBlock Text="Text"/>
			</Grid>
		</Border>
	</Canvas>
</Grid>

最后是cs后台代码部分


public partial class MainWindow : Window
{
	private MainViewModel vm;
	private bool isMouseDown=false;
	private Point mousePosition=new Point();
	private TranslateTransform translateTransform=new TranslateTransform();
	private ScaleTransform scaleTransform=new ScaleTransform();
	private TransformGroup transformGroup=new TransformGroup();
	public MainWindow()
	{
		InitializeComponent();
		vm=DataContext as MainViewModel;
		transformGroup.Children.Add(scaleTransform);//定义缩放
		transformGroup.Children.Add(translateTransform);//定义移动
		border.RenderTransform=transformGroup;//定义变换组
		canvas.Loaded+=(s,e)=>
		{
			//初始化border控件大小适配canvas父容器
			var scale = Math.Min(canvas.ActualWidth/border.Width,canvas.ActualHeight/border.Height);
			scaleTransform.ScaleX=scale;
			scaleTransform.ScaleY=scale;
		};
	}
	private void Canvas_MouseRightButtonDown(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=true;
		mousePosition=e.GetPosition(canvas);
	}
	private void Canvas_MouseRightButtonUp(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=false;
	}
	private void Canvas_MouseLeftButtonDown(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=true;
		mousePosition=e.GetPosition(canvas);
	}
	private void Canvas_MouseLeftButtonUp(object sender,MouseButtonEventArgs e)
	{
		isMouseDown=false;
	}
	private void Canvas_MouseMove(object sender,MouseEventArgs e)
	{
		var position=e.GetPosition(canvas);
		vm.MouseX=position.X;
		vm.MouseY=position.Y;
		if(isMouseDown)
		{
			TranslateTransform translateTransform = transformGroup.Children[1] as TranslateTransform ;
			translateTransform.X+=position.X-mousePosition.X;
			translateTransform.Y+=position.Y-mousePosition.Y;
			mousePosition=position;
		}
	}
	private void Canvas_MouseWheel(object sender,MouseWheelEventArgs e)
	{
		vm.Delta=e.Delta;
		double scale=e.Delta*0.001;
		var position=e.GetPosition(canvas);
		vm.MouseX=position.X;
		vm.MouseY=position.Y;
		Point inversePoint=transformGroup.Inverse.Transform(position);
		ScaleTransform scaleTransform = transformGroup.Children[0] as ScaleTransform;
		TranslateTransform translateTransform = transformGroup.Children[1] as TranslateTransform ;
		if(scaleTransform.ScaleX+scale<1)return;
		scaleTransform.ScaleX+=scale;
		scaleTransform.ScaleY+=scale;
		translateTransform.X=-1*((inversePoint.X*scaleTransform.ScaleX)-position.X);
		translateTransform.Y=-1*((inversePoint.Y*scaleTransform.ScaleY)-position.Y);
	}

}


在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值