Преобразование точек с изображения в точки UIImageView, contentMode-aware
Скажем, у меня есть изображение (например, 1024 x 768 px), которое отображается в UIImageView (например, 300 x 300 пикселей).
Теперь я хотел бы преобразовать точку из изображения, например. положение носа человека (x: 500, y: 600), в соответствующую точку на UIImageView с учетом его contentMode.
Если contentMode зафиксирован в UIViewContentModeScaleToFill, преобразование будет простым. Но если это UIViewContentModeScaleAspectFit, все становится более сложным.
Есть ли элегантный способ достичь этого? Я действительно не хочу вычислять это для каждого единственного contentMode (более 10, я думаю).
Спасибо!
Ответы
Ответ 1
Сегодня у меня было свободное время, чтобы собрать решение этой проблемы и опубликовать ее на GitHub: UIImageView-GeometryConversion
Это категория в UIImageView, которая предоставляет методы для преобразования точек и прямоугольников из изображения для просмотра координат и соблюдения всех 13 различных режимов содержимого.
Надеюсь, вам понравится!
Ответ 2
Это мое быстрое решение:
- (CGPoint)convertPoint:(CGPoint)sourcePoint fromContentSize:(CGSize)sourceSize {
CGPoint targetPoint = sourcePoint;
CGSize targetSize = self.bounds.size;
CGFloat ratioX = targetSize.width / sourceSize.width;
CGFloat ratioY = targetSize.height / sourceSize.height;
if (self.contentMode == UIViewContentModeScaleToFill) {
targetPoint.x *= ratioX;
targetPoint.y *= ratioY;
}
else if(self.contentMode == UIViewContentModeScaleAspectFit) {
CGFloat scale = MIN(ratioX, ratioY);
targetPoint.x *= scale;
targetPoint.y *= scale;
targetPoint.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetPoint.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
}
else if(self.contentMode == UIViewContentModeScaleAspectFill) {
CGFloat scale = MAX(ratioX, ratioY);
targetPoint.x *= scale;
targetPoint.y *= scale;
targetPoint.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetPoint.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
}
return targetPoint;
}
- (CGRect)convertRect:(CGRect)sourceRect fromContentSize:(CGSize)sourceSize {
CGRect targetRect = sourceRect;
CGSize targetSize = self.bounds.size;
CGFloat ratioX = targetSize.width / sourceSize.width;
CGFloat ratioY = targetSize.height / sourceSize.height;
if (self.contentMode == UIViewContentModeScaleToFill) {
targetRect.origin.x *= ratioX;
targetRect.origin.y *= ratioY;
targetRect.size.width *= ratioX;
targetRect.size.height *= ratioY;
}
else if(self.contentMode == UIViewContentModeScaleAspectFit) {
CGFloat scale = MIN(ratioX, ratioY);
targetRect.origin.x *= scale;
targetRect.origin.y *= scale;
targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
targetRect.size.width *= scale;
targetRect.size.height *= scale;
}
else if(self.contentMode == UIViewContentModeScaleAspectFill) {
CGFloat scale = MAX(ratioX, ratioY);
targetRect.origin.x *= scale;
targetRect.origin.y *= scale;
targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
targetRect.size.width *= scale;
targetRect.size.height *= scale;
}
return targetRect;
}
Когда он будет реорганизован и оптимизирован, я опубликую его на github и отправлю ссылку здесь.
Возможно, даже этот фрагмент может быть полезен для кого-то.
Ответ 3
Нет, нет встроенного, открытого или элегантного способа сделать это.
Вам нужно перепроектировать функции для режимов контента, в которых вы нуждаетесь.
Ответ 4
Почему вы не можете просто перемасштабировать координаты:
X (UIImageView) = (X (изображение)/1024) * 300
и
Y (UIImageView) = (Y (изображение)/768) * 300