Применение масштабирования и поворота в представлении с использованием CGAffineTransform

Поэтому мне нужно применить некоторое масштабирование и некоторое вращение к представлению (я делаю это с помощью жестов), поэтому для каждого жестов я обновляю текущие значения scalling и rotation с помощью чего-то вроде:

self.scaleWidth *= gesture.scale; //When I detect an horizontal pinch
self.scaleHeight *= gesture.scale; //When I detect a vertical pinch
self.rotationAngle += gesture.rotationAngle; //When I detect a rotation

Затем я делаю следующее, чтобы преобразовать представление:

CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, self.scaleWidth, self.scaleHeight);
self.theSubViewToTransform.transform = CGAffineTransformRotate(transform, self.rotationAngle);

Когда я делаю только масштабирование, он отлично работает. Когда я делаю масштабирование, а затем вращаюсь, он вращается нормально. Когда после поворота я снова пытаюсь масштабировать, он не работает нормально: шкала применяется, как если бы она выполнялась после вращения, деформируя структуру изображения.

Я думал, что сделал все, что нужно было сделать, чтобы избежать этого: каждый раз начинать с преобразования идентичности, сначала масштабируя, а затем поворачивать, но, очевидно, я ошибался...

Кто-нибудь знает, что случилось с моей реализацией?

Спасибо

Ответ 1

Если вы начинаете с преобразования идентичности каждый раз, конечный результат, который вы устанавливаете преобразованием subview, будет включать только масштабирование и поворот из текущего жеста. Вместо того, чтобы начинать с идентификатора, начните с текущего преобразования представления.

CGAffineTransform transform = self.theSubViewToTransform.transform;
transform = CGAffineTransformScale(transform, self.scaleWidth, self.scaleHeight);
transform = CGAffineTransformRotate(transform, self.rotationAngle);
self.theSubViewToTransform.transform = transform;

В первый раз, когда это выполняется, преобразование начнется как преобразование идентичности. При последующих исполнениях новые изменения будут перенесены поверх старых.

Ответ 2

Вы должны начать с вашего текущего преобразованного состояния и применить преобразование, которое ожидается. Также вы можете взглянуть на CGAffineTransformConcat, перед тем, как применить, он сделает одно преобразование.

CGAffineTransform transform = yourView.transform;
transform = CGAffineTransformConcat(CGAffineTransformScale(transform,  self.scaleWidth, self.scaleHeight),
                                    CGAffineTransformRotate(transform, self.rotationAngle));
yourView.transform = transform;

Надеюсь, что это поможет!

Ответ 3

Для быстрого 3:

view.transform = CGAffineTransform(rotationAngle:  CGFloat.pi).concatenating(CGAffineTransform(scaleX: 0.4, y: 0.4))

Ответ 4

Попробуйте применить преобразования к тождественному преобразованию, например.

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, scaleWidth, scaleHeight);
transform = CGAffineTransformRotate(transform, angle);
viewToTransform.transform = transform;