ios - 旋转后翻译 UIView

标签 ios objective-c rotation translation cgaffinetransform

我正在尝试翻译已使用用户触摸旋转和/或缩放的 UIView。我也尝试用用户输入来翻译它:

- (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];
}

但是当我触摸并移动 View 时,它会以各种奇怪的方式进行转换。我可以应用某种使用旋转值的公式来正确翻译吗?

最佳答案

我发现必须使用最少的数学运算的最佳解决方案是分别存储原始平移、旋转和缩放值,并在它们发生更改时重做变换。我的解决方案是使用以下属性对 UIView 进行子类化:

@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];
    }
}

关于ios - 旋转后翻译 UIView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21950129/

相关文章:

ios - SoundCloud API 流质量

ios - Jenkins 在不生成 IPA 文件的情况下成功

ios - 随机唯一字符串生成用作随机数(oauth)

Android - 将图像垂直发送到服务器时,尽管移动设备中的预览看起来不错,但它们会旋转

jQuery Rotate 在几次使用后滞后

ios - 在 Xamarin 中使用 transitionWithView 设置 UIView.Hidden 属性时淡入淡出动画

iOS - 关闭 View Controller 后标签栏变为透明

iphone - 按创建日期对 NSURL 对象数组进行排序

matlab - 在matlab中有效地从球体上的多个圆中均匀采样

ios - 在属性集上定义 setter 方法