public class PZBehavior : 振る舞い {
bool _isDragging;
bool _isPinching;
Point _ptPinchPositionStart;
private Image _imgZoom;
private ScaleTransform _scaleTransform;
private RotateTransform _rotateTransform;
private TranslateTransform _translateTransform;
private MatrixTransform _previousTransform;
private TransformGroup _parentGroup;
private TransformGroup _currentTransform;
protected override void OnAttached()
{
_imgZoom = AssociatedObject;
_imgZoom.RenderTransform = BuildTrasnformGroup();
var listener = GestureService.GetGestureListener(AssociatedObject);
listener.DragStarted += DragStarted;
listener.DragDelta += DragDelta;
listener.DragCompleted += DragCompleted;
listener.PinchStarted += PinchStarted;
listener.PinchDelta += PinchDelta;
listener.PinchCompleted += PinchCompleted;
}
private TransformGroup BuildTrasnformGroup()
{
_parentGroup = new TransformGroup();
_currentTransform = new TransformGroup();
_previousTransform = new MatrixTransform();
_scaleTransform = new ScaleTransform();
_rotateTransform = new RotateTransform();
_translateTransform = new TranslateTransform();
_currentTransform.Children.Add(_scaleTransform);
_currentTransform.Children.Add(_rotateTransform);
_currentTransform.Children.Add(_translateTransform);
_parentGroup.Children.Add(_previousTransform);
_parentGroup.Children.Add(_currentTransform);
return _parentGroup;
}
void PinchCompleted(object sender, PinchGestureEventArgs e)
{
if (_isPinching)
{
TransferTransforms();
_isPinching = false;
}
}
void PinchDelta(object sender, PinchGestureEventArgs e)
{
if (_isPinching)
{
// Set scaling
_scaleTransform.ScaleX = e.DistanceRatio;
_scaleTransform.ScaleY = e.DistanceRatio;
// Optionally set rotation
_rotateTransform.Angle = e.TotalAngleDelta;
// Set translation
Point ptPinchPosition = new Point(0,0);
_translateTransform.X = ptPinchPosition.X - _ptPinchPositionStart.X;
_translateTransform.Y = ptPinchPosition.Y - _ptPinchPositionStart.Y;
}
}
void PinchStarted(object sender, PinchStartedGestureEventArgs e)
{
_isPinching = e.OriginalSource == _imgZoom;
if (_isPinching)
{
// Set transform centers
Point ptPinchCenter = e.GetPosition(_imgZoom);
ptPinchCenter = _previousTransform.Transform(ptPinchCenter);
_scaleTransform.CenterX = ptPinchCenter.X;
_scaleTransform.CenterY = ptPinchCenter.Y;
_rotateTransform.CenterX = ptPinchCenter.X;
_rotateTransform.CenterY = ptPinchCenter.Y;
_ptPinchPositionStart = new Point(0,0);
}
}
void DragCompleted(object sender, DragCompletedGestureEventArgs e)
{
if (_isDragging)
{
TransferTransforms();
_isDragging = false;
}
}
void DragDelta(object sender, DragDeltaGestureEventArgs e)
{
if (_isDragging)
{
_translateTransform.X += e.HorizontalChange;
_translateTransform.Y += e.VerticalChange;
}
}
void DragStarted(object sender, DragStartedGestureEventArgs e)
{
_isDragging = e.OriginalSource == _imgZoom;
}
void TransferTransforms()
{
_previousTransform.Matrix = Multiply(_previousTransform.Matrix, _currentTransform.Value);
// Set current transforms to default values
_scaleTransform.ScaleX = _scaleTransform.ScaleY = 1;
_scaleTransform.CenterX = _scaleTransform.CenterY = 0;
_rotateTransform.Angle = 0;
_rotateTransform.CenterX = _rotateTransform.CenterY = 0;
_translateTransform.X = _translateTransform.Y = 0;
}
Matrix Multiply(Matrix a, Matrix b)
{
return new Matrix(a.M11 * b.M11 + a.M12 * b.M21,
a.M11 * b.M12 + a.M12 * b.M22,
a.M21 * b.M11 + a.M22 * b.M21,
a.M21 * b.M12 + a.M22 * b.M22,
a.OffsetX * b.M11 + a.OffsetY * b.M21 + b.OffsetX,
a.OffsetX * b.M12 + a.OffsetY * b.M22 + b.OffsetY);
}
}