2015-11-02 5 views
2

У меня очень простой UIImageView, который содержится в виде контейнера. Они имеют одинаковый размер, не используется автоматическая компоновка. Когда пользователь нажимает кнопку, UIImageView следует поворачивать на 90 градусов. Когда UIImageView (не UIImageView.image) повернут, он должен соответствовать его надзору (.ScaleAspectFit). До сих пор я выяснил самую легкую часть: преобразование вращения.Как найти раму UIView после преобразования вращения

self.currentRotation += 90 
    if self.currentRotation >= 360 { 
     self.currentRotation = 0 
    } 

    let angleInRadians: Double 
    switch self.currentRotation { 
    case 0: 
     angleInRadians = 0 
    case 90: 
     angleInRadians = M_PI_2 
    case 180: 
     angleInRadians = M_PI 
    case 270: 
     angleInRadians = M_PI + M_PI_2 
    default: 
     angleInRadians = 0 
     break; 
    } 
    let newTransform = CGAffineTransformRotate(CGAffineTransformIdentity, CGFloat(angleInRadians)) 

Получая информацию от this question, я был в состоянии написать Swift версии вспомогательных расширений, но я до сих пор не могу понять, как найти рамку UIImageView в.

extension UIView { 
    var originalFrame: CGRect { 
     let currentTransform = self.transform 
     self.transform = CGAffineTransformIdentity 
     let originalFrame = self.frame 
     self.transform = currentTransform 
     return originalFrame 
    } 

    var transformedTopLeftPoint: CGPoint { 
     return self.transformedPointForOriginalPoint(originalFrame.topLeftPoint) 
    } 

    var transformedTopRightPoint: CGPoint { 
     return self.transformedPointForOriginalPoint(originalFrame.topRightPoint) 
    } 

    var transformedBottomLeftPoint: CGPoint { 
     return self.transformedPointForOriginalPoint(originalFrame.bottomLeftPoint) 
    } 

    var transformedBottomRightPoint: CGPoint { 
     return self.transformedPointForOriginalPoint(originalFrame.bottomRightPoint) 
    } 

    // helper to get point offset from center 
    func centerOffset(point: CGPoint) -> CGPoint { 
     return CGPoint(x: point.x - self.center.x, y: point.y - self.center.y) 
    } 

    // helper to get point back relative to center 
    func pointRelativeToCenter(point: CGPoint) -> CGPoint { 
     return CGPoint(x: point.x + self.center.x, y: point.y + self.center.y) 
    } 

    // helper to get point relative to transformed coords 
    func transformedPointForOriginalPoint(point: CGPoint) -> CGPoint { 
     // get offset from center 
     let offset = self.centerOffset(point) 
     // get transformed point 
     let transformedPoint = CGPointApplyAffineTransform(offset, self.transform) 
     // make relative to center 
     return self.pointRelativeToCenter(transformedPoint) 
    } 
} 

extension CGRect { 
    var topLeftPoint: CGPoint { 
     return self.origin 
    } 

    var topRightPoint: CGPoint { 
     return CGPoint(x: self.origin.x + self.size.width, y: self.origin.y) 
    } 

    var bottomLeftPoint: CGPoint { 
     return CGPoint(x: self.origin.x, y: self.origin.y + self.size.height) 
    } 

    var bottomRightPoint: CGPoint { 
     return CGPoint(x: self.origin.x + self.size.width, y: self.origin.y + self.size.height) 
    } 
} 

Для лучшего уточнения, я прикрепляю изображение.

image for better understanding

Это показывает, повернутый вид сверху его исходного кадра (наименьшее из Контуры) и обновленного кадра (самый большой серый контур). Круги указывают верхний правый угол обзора до и после вращения. После применения преобразования кадр обновляется до минимального ограничивающего прямоугольника , который охватывает вид. Его новое происхождение ( верхний левый угол серой внешней коробки) практически не имеет ничего общего с с исходным видом происхождения (верхний левый угол черного невращающийся внутренний ящик). iOS не предоставляет способ для получения скорректированной точки . Вот серия методов представления, которые выполняют для вас математику . (Расширение UIView выше)

Мне нужно найти рамку с серой коробкой. Но даже с этими методами я все еще не могу понять, как это сделать. Какова формула/алгоритм для достижения того, что я хочу?

+0

Простой. Трансформированный кадр представления является ограничивающим прямоугольником этого представления. Так что просто используйте фрейм. – kirander

+0

@kirander Но согласно документации при настройке пользовательского преобразования в UIView, свойство frame становится неопределенным и не должно использоваться вообще. – xinatanil

+0

Да, это правда, но подсказка - это рамка трансформированного представления, описывающая минимальный ограничивающий прямоугольник. Почему бы не использовать это? – kirander

ответ

2

После преобразования centre преобразованного вида остается неизменным. Поэтому вам нужно рассчитать вещи с точки зрения центра. Что-то вроде этого:

func originalFrame() -> CGRect { 
    CGAffineTransform currentTransform = self.transform; 
    self.transform = CGAffineTransformIdentity; 
    let originalFrame = self.frame; 
    self.transform = currentTransform; 

    return originalFrame; 
} 

func centerOffset(point:CGPoint) -> CGPoint { 
    return CGPointMake(point.x - self.center.x, point.y - self.center.y); 
} 

func pointRelativeToCenter(point:CGPoint) -> CGPoint { 
    CGPointMake(point.x + self.center.x, point.y + self.center.y); 
} 


func newPointInView(point:CGPoint) -> CGPoint { 
    let offset = self.centerOffset(point) 
    let transformedPoint = CGPointApplyAffineTransform(offset, self.transform); 
    return self.pointRelativeToCenter(transformedPoint) 
} 

func newTopLeft() -> CGPoint { 
    let frame = self.originalFrame() 
    return self.newPointInView(frame) 
} 

func newTopRight() -> CGPoint { 
    let frame = self.originalFrame() 
    var point = frame.origin 
    point.x = point.x + frame.size.width 
    return self.newPointInView(point) 
} 


func newBottomLeft() -> CGPoint { 
    let frame = self.originalFrame() 
    var point = frame.origin 
    point.y = point.y + frame.size.height 
    return self.newPointInView(point) 
} 


func newBottomRight() -> CGPoint { 
    let frame = self.originalFrame() 
    var point = frame.origin 
    point.x = point.x + frame.size.width 
    point.y = point.y + frame.size.height 
    return self.newPointInView(point) 
} 

См. Это SO Thread для более подробной информации.

0

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

// after transform 
// obj-c 
CGRect boundingBoxFrame = myTransformedImageView.frame; 
+0

Извините, до сих пор не понимаю. Предлагаете ли вы найти преобразованный кадр представления, объединив его границы с чем-то другим? Не могли бы вы предоставить образец кода? У меня была долгая ночь, и я был бы признателен за более подробный ответ. – xinatanil

+0

Я отредактировал ответ. – kirander

+0

Спасибо за подробный ответ, он действительно работает. Но не могли бы вы объяснить опасности этого метода? Согласно документации «Если свойство transform не является преобразованием идентичности, значение свойства frame не определено и поэтому должно игнорироваться.«Преобразование UIImageView, определенно, не CGAffineTransformIdentity, и я боюсь, что рано или поздно мне придется найти другой способ расчета рамки трансформированного представления. – xinatanil

Смежные вопросы