UIView translation after rotation

I am trying to translate a UIView that has been rotated and / or scaled using user touches. I am also trying to translate it using a user:

- (void)handleObjectMove:(UIPanGestureRecognizer *)recognizer
{
    static CGPoint lastPoint;
    UIView *moveView = [recognizer view];
    CGPoint newCoord = [recognizer locationInView:playArea];

    // Check if this is the first touch
    if( [recognizer state]==UIGestureRecognizerStateBegan )
    {
        // Store the initial touch so when we change positions we do not snap
        lastPoint = newCoord;
    }

    // Create the frame offsets to use our finger position in the view.
    float dX = newCoord.x;
    float dY = newCoord.y;

    dX-=lastPoint.x;
    dY-=lastPoint.y;

    // Figure out the translation based on how we are scaled
    CGAffineTransform transform = [moveView transform];
    CGFloat xScale = transform.a;
    CGFloat yScale = transform.d;

    dX/=xScale;
    dY/=yScale;

    lastPoint = newCoord;

    [moveView setTransform:CGAffineTransformTranslate( transform, dX, dY )];

    [recognizer setTranslation:CGPointZero inView:playArea];
}

But when I touch and move the view, it transforms in all different strange ways. Can I apply some formula using rotation values ​​for the correct translation?

+3
source share
3 answers

The best solution I found to use the least amount of math was to keep the original translation, rotation, and scaling values ​​separate and redo the transformation when they change. My solution was to subclass UIView with the following properties:

@property (nonatomic) CGPoint translation;
@property (nonatomic) CGFloat rotation;
@property (nonatomic) CGPoint scaling;

:

- (void)rotationDelta:(CGFloat)delta
{
    [self setRotation:[self rotation]+delta];
}

- (void)scalingDelta:(CGPoint)delta
{
    [self setScaling:
     (CGPoint){ [self scaling].x*delta.x, [self scaling].y*delta.y }];
}

- (void)translationDelta:(CGPoint)delta
{
    [self setTranslation:
     (CGPoint){ [self translation].x+delta.x, [self translation].y+delta.y }];
}

- (void)transformMe
{
    // Start with the translation
    CGAffineTransform transform = CGAffineTransformMakeTranslation( [self translation].x, [self translation].y );
    // Apply scaling
    transform = CGAffineTransformScale( transform, [self scaling].x, [self scaling].y );
    // Apply rotation
    transform = CGAffineTransformRotate( transform, [self rotation] );

    [self setTransform:transform];
}

- (void)setScaling:(CGPoint)newScaling
{
    scaling = newScaling;
    [self transformMe];
}

- (void)setRotation:(CGFloat)newRotation
{
    rotation = newRotation;
    [self transformMe];
}

- (void)setTranslation:(CGPoint)newTranslation
{
    translation = newTranslation;
    [self transformMe];
}

:

- (void)handleObjectPinch:(UIPinchGestureRecognizer *)recognizer
{
    if( [recognizer state] == UIGestureRecognizerStateEnded
        || [recognizer state] == UIGestureRecognizerStateChanged )
    {
        // Get my stuff
        if( !selectedView )
            return;

        SelectableImageView *view = selectedView;

        CGFloat scaleDelta = [recognizer scale];
        [view scalingDelta:(CGPoint){ scaleDelta, scaleDelta }];

        [recognizer setScale:1.0];
    }
}

- (void)handleObjectMove:(UIPanGestureRecognizer *)recognizer
{
    static CGPoint lastPoint;
    SelectableImageView *moveView = (SelectableImageView *)[recognizer view];
    CGPoint newCoord = [recognizer locationInView:playArea];

    // Check if this is the first touch
    if( [recognizer state]==UIGestureRecognizerStateBegan )
    {
        // Store the initial touch so when we change positions we do not snap
        lastPoint = newCoord;
    }

    // Create the frame offsets to use our finger position in the view.
    float dX = newCoord.x;
    float dY = newCoord.y;

    dX-=lastPoint.x;
    dY-=lastPoint.y;
    lastPoint = newCoord;

    [moveView translationDelta:(CGPoint){ dX, dY }];

    [recognizer setTranslation:CGPointZero inView:playArea];
}

- (void)handleRotation:(UIRotationGestureRecognizer *)recognizer
{
    if( [recognizer state] == UIGestureRecognizerStateEnded
       || [recognizer state] == UIGestureRecognizerStateChanged )
    {
        if( !selectedView )
            return;

        SelectableImageView *view = selectedView;

        CGFloat rotation = [recognizer rotation];
        [view rotationDelta:rotation];

        [recognizer setRotation:0.0];
    }
}
+2

moveView.center Set (x, y) "CGAffineTransformTranslate"

0

, . 2:

:

self.view.addSubview(topView)

PanGesture :

//Add PanGestureRecognizer to move
    let panMoveGesture = UIPanGestureRecognizer(target: self, action: #selector(YourViewController.moveViewPanGesture(_:)))
    topView.addGestureRecognizer(panMoveGesture)

:

//Move function
func moveViewPanGesture(recognizer:UIPanGestureRecognizer)
{
    if recognizer.state == .Changed {
        var center = recognizer.view!.center
        let translation = recognizer.translationInView(recognizer.view?.superview)
        center = CGPoint(x:center.x + translation.x,
                             y:center.y + translation.y)
        recognizer.view!.center = center
        recognizer.setTranslation(CGPoint.zero, inView: recognizer.view)
    }
}

, , , . : recognizer.view?.superview , , , - , , ( ), . .

-1
source

All Articles