一个Pan&Zoom的Behavior

Pan&Zoom是个很常用的操作,但是不想每次都去重新写各种GerstureListener事件,所以就参考这篇文章,改写了个简单的Behavior。

public class ZoomAndPanBehavior2 : Behavior<Image>
{
private Image _currentImage { get { return AssociatedObject as Image; } }
 
private PhoneApplicationPage _currentPage
{
get
{
var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
var currentPage = rootFrame.Content as PhoneApplicationPage;
return currentPage;
}
}
 
private GestureListener _gl { get { return GestureService.GetGestureListener(_currentImage); } }
 
private double _totalImageScale = 1d;
private Point _imagePosition = new Point(0, 0);
 
private Point _oldFinger1;
private Point _oldFinger2;
private double _oldScaleFactor; //旧的缩放因子
 
private CompositeTransform _compositeTransfrom;
private MatrixTransform _previousTransform;
private TransformGroup _transfromGruop;
private TransformGroup _currentGroup;
 
bool isDragging;
bool isPinching;
Point ptPinchPositionStart;
 
protected override void OnAttached()
{
base.OnAttached();
_compositeTransfrom = new CompositeTransform();
_previousTransform = new MatrixTransform { Matrix = Matrix.Identity };
_transfromGruop = new TransformGroup();
_currentGroup = new TransformGroup();
_currentGroup.Children.Add(_compositeTransfrom);
_transfromGruop.Children.Add(_currentGroup);
_transfromGruop.Children.Add(_previousTransform);
_currentImage.RenderTransform = _transfromGruop;
_currentImage.RenderTransformOrigin = new Point(0, 0);
_gl.DragStarted += _gl_DragStarted;
_gl.DragDelta += _gl_DragDelta;
_gl.PinchStarted += _gl_PinchStarted;
_gl.PinchDelta += _gl_PinchDelta;
_gl.PinchCompleted += _gl_PinchCompleted;
_gl.Hold += _gl_Hold;
_gl.DoubleTap += _gl_DoubleTap;
}
 
protected override void OnDetaching()
{
base.OnDetaching();
_gl.DragStarted -= _gl_DragStarted;
_gl.DragDelta -= _gl_DragDelta;
_gl.PinchStarted -= _gl_PinchStarted;
_gl.PinchDelta -= _gl_PinchDelta;
_gl.PinchCompleted -= _gl_PinchCompleted;
_gl.Hold -= _gl_Hold;
_gl.DoubleTap -= _gl_DoubleTap;
_compositeTransfrom = null;
}
 
void _gl_DoubleTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
{
Point imageCenter = e.GetPosition(_currentImage);
if (_compositeTransfrom.ScaleX != 2)
_compositeTransfrom.ScaleY = _compositeTransfrom.ScaleX = 2;
else
_compositeTransfrom.ScaleX = _compositeTransfrom.ScaleY = 1;
_compositeTransfrom.CenterX = imageCenter.X;
_compositeTransfrom.CenterY = imageCenter.Y;
}
 
void _gl_Hold(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
{
 
}
 
void _gl_PinchStarted(object sender, PinchStartedGestureEventArgs e)
{
_oldFinger1 = e.GetPosition(_currentImage, 0);
_oldFinger2 = e.GetPosition(_currentImage, 1);
_oldScaleFactor = 1;
isPinching = true;
}
void _gl_PinchDelta(object sender, PinchGestureEventArgs e)
{
//DistanceRatio表示缩放之后手指之间的距离与缩放前手指之间距离的比例
var scaleFactor = e.DistanceRatio / _oldScaleFactor;
 
var currentFinger1 = e.GetPosition(_currentImage, 0);
var currentFinger2 = e.GetPosition(_currentImage, 1);
 
Point tranlationDelta;
tranlationDelta = GetTranslationDelta(currentFinger1, currentFinger2, _oldFinger1, _oldFinger2, _imagePosition, scaleFactor);
 
_oldFinger1 = currentFinger1;
_oldFinger2 = currentFinger2;
_oldScaleFactor = e.DistanceRatio;
UpdateImage(scaleFactor, tranlationDelta);
}
 
void _gl_PinchCompleted(object sender, PinchGestureEventArgs e)
{
isPinching = false;
}
 
void _gl_DragStarted(object sender, DragStartedGestureEventArgs e)
{
 
}
 
void _gl_DragDelta(object sender, DragDeltaGestureEventArgs e)
{
if (isPinching)
return;
if (_totalImageScale > 1 || _compositeTransfrom.ScaleX > 1)
{
_compositeTransfrom.TranslateX += e.HorizontalChange;
_compositeTransfrom.TranslateY += e.VerticalChange;
}
}
 
private void UpdateImage(double scaleFactor, Point delta)
{
_totalImageScale *= scaleFactor;
_imagePosition = new Point(_imagePosition.X + delta.X, _imagePosition.Y + delta.Y);
 
if (_totalImageScale > 1)
{
_compositeTransfrom.ScaleX = _totalImageScale;
_compositeTransfrom.ScaleY = _totalImageScale;
_compositeTransfrom.TranslateX = _imagePosition.X;
_compositeTransfrom.TranslateY = _imagePosition.Y;
}
else
{
_compositeTransfrom.ScaleX = _compositeTransfrom.ScaleY = 1;
_compositeTransfrom.TranslateX = _compositeTransfrom.TranslateY = 0;
_imagePosition = new Point(0, 0);
}
}
 
private Point GetTranslationDelta(Point currentFinger1, Point currentFinger2, Point oldFinger1,
Point oldFinger2, Point currentPosition, double scaleFactor)
{
var newPos1 = new Point(
currentFinger1.X + (currentPosition.X - oldFinger1.X) * scaleFactor,
currentFinger1.Y + (currentPosition.Y - oldFinger1.Y) * scaleFactor);
 
var newPos2 = new Point(
currentFinger2.X + (currentPosition.X - oldFinger2.X) * scaleFactor,
currentFinger2.Y + (currentPosition.Y - oldFinger2.Y) * scaleFactor);
 
var newPos = new Point(
(newPos1.X + newPos2.X) / 2,
(newPos1.Y + newPos2.Y) / 2);
 
return new Point(
newPos.X - currentPosition.X,
newPos.Y - currentPosition.Y);
}
}

转载于:https://www.cnblogs.com/walleyekneel/archive/2013/06/13/3133712.html

内容概要:本文详细介绍了施耐德M580系列PLC的存储结构、系统硬件架构、上电写入程序及CPU冗余特性。在存储结构方面,涵盖拓扑寻址、Device DDT远程寻址以及寄存器寻址三种方式,详细解释了不同类型的寻址方法及其应用场景。系统硬件架构部分,阐述了最小系统的构建要素,包括CPU、机架和模块的选择与配置,并介绍了常见的系统拓扑结构,如简单的机架间拓扑和远程子站以太网菊花链等。上电写入程序环节,说明了通过USB和以太网两种接口进行程序下载的具体步骤,特别是针对初次下载时IP地址的设置方法。最后,CPU冗余部分重点描述了热备功能的实现机制,包括IP通讯地址配置和热备拓扑结构。 适合人群:从事工业自动化领域工作的技术人员,特别是对PLC编程及系统集成有一定了解的工程师。 使用场景及目标:①帮助工程师理解施耐德M580系列PLC的寻址机制,以便更好地进行模块配置和编程;②指导工程师完成最小系统的搭建,优化系统拓扑结构的设计;③提供详细的上电写入程序指南,确保程序下载顺利进行;④解释CPU冗余的实现方式,提高系统的稳定性和可靠性。 其他说明:文中还涉及一些特殊模块的功能介绍,如定时器事件和Modbus串口通讯模块,这些内容有助于用户深入了解M580系列PLC的高级应用。此外,附录部分提供了远程子站和热备冗余系统的实物图片,便于用户直观理解相关概念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值