iOS - Swift - кликабельные области на UIImage - PullRequest
0 голосов
/ 03 ноября 2018

Я работаю над проектом, в котором мне нужно нанести точки в определенных областях на изображение, представляющее человеческое тело. В Интерфейсном Разработчике я установил контейнер UIView, который занимает большую часть вертикального центра основного вида. В этом представлении контейнера я поместил UIImageView и установил изображение в IB. Графика намного больше, чем UIImageView и контейнер UIView, точнее, она выше. ContentMode UIImageView установлен в AspectFit, потому что я хочу, чтобы изображение не показывалось как больше, чем контейнер.

Код создает несколько экземпляров CGRect, которые являются областями, где касания пользователя что-то значат. Когда пользователь нажимает на представление контейнера, код используется для определения, находится ли точка в одной из областей, и если это так, в центре этой области рисуется точка.

Проблема в том, что когда я запускаю приложение на определенных симуляторах, прямоугольники региона не в нужном месте на изображении. Например, когда я запускаю приложение на iPhone X, область прямоугольника, которая находится на месте для головы, выглядит хорошо. Когда я запускаю приложение на iPhone XR, область прямоугольника отключается слева от головы.

enter image description here enter image description here

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

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

Обновление 1 : UIImageView прикреплен к окружающему UIView, поэтому его ширина и высота такие же большие, как у контейнера. Поскольку изображение более тонкое, чем UIImageView, изображение отображается по центру. На прикрепленных изображениях фиолетовый фон - это UIImageView, показывающий самый верхний цвет фона UIView.

Обновление 2 : я проверил шкалу ширины и высоты и обнаружил, что они разные. Коэффициент масштабирования по ширине равен 1.36565656565, а коэффициент масштабирования по высоте равен 2.104. Я попробовал формулы, приведенные с обоими масштабными коэффициентами, заданными Sweeper, но не повезло.

Ответы [ 3 ]

0 голосов
/ 03 ноября 2018

Я сделал этот код для прямоугольника в том же положении на каждом устройстве. Чтобы проверить, является ли это телефон x, я делаю это в viewDidLoad и устанавливаю ограничения на то, что я хочу, и добавляю размер панели вкладок.

@IBOutlet weak var tabMenu:          NSLayoutConstraint!
@IBOutlet weak var topConstraint:    NSLayoutConstraint!
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

@IBOutlet weak var backgroundImg: UIImageView!
@IBOutlet weak var rectangleImg:  UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Check if it's a iPhone X
    if #available(iOS 11, *) {
        let safeArea = UIApplication.shared.delegate?.window??.safeAreaInsets

        // If its a x phone i use safe instead of superView
        guard let safe = safeArea else { return }
        if safe.bottom > 0 {
            topConstraint.constant = safe.top
            bottomConstraint.constant = safe.bottom + tabMenu.constant
        }
    }
}

override func viewDidAppear(_ animated: Bool) {

    // Here I set the rectangle to 36% of the width and height (change to what you want)
    rectangleImg.frame = CGRect(x: 0, y: 0, width: backgroundImg.frame.width * 0.36,
    height: backgroundImg.frame.height * 0.36)

    // Last I put the rectangle in the center of background image
    rectangleImg.center.x = backgroundImg.center.x
    rectangleImg.center.y  = backgroundImg.center.y

}

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

0 голосов
/ 06 ноября 2018

Корень моей проблемы в том, что четыре стороны UIImageView были прикреплены к его виду контейнера. Когда ширина устройства изменилась, оно правильно масштабировало изображение, но это вызвало растяжение изображения. Это вызвало, например, увеличение ширины головы. На данный момент я решил эту проблему, зафиксировав ширину изображения, чтобы координаты, которые я придумала из исходного изображения, остались без изменений, независимо от того, какое устройство.

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

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

0 голосов
/ 03 ноября 2018

Вам просто нужно немного посчитать.

На исходном изображении укажите регион, который пользователь может нажать. Запишите его x, y, w, h относительно изображения.

Выясните, насколько уменьшилось изображение при просмотре изображения. Поскольку вы сказали, что изображение выше, чем изображение, оно подверглось масштабному коэффициенту imageViewHeight / imageHeight. Теперь мы будем называть это scaleFactor.

Координата Y региона также должна была уменьшиться на scaleFactor, поэтому вы умножаете regionY на scaleFactor, чтобы получить newY.

Ширина и высота региона будут делать то же самое, поэтому умножьте их на scaleFactor и получите newWidth и newHeight.

Координата X области относительно вида изображения немного хитрая. Вам необходимо учитывать количество пустого пространства, созданного представлением изображения, путем его уменьшения. Это emptySpace рассчитывается по (imageViewWidth - newWidth) / 2. Затем, чтобы вычислить координату X новой области относительно вида изображения, вы делаете emptySpace + X * scaleFactor.

Теперь прямоугольник (newX, newY, newWidth, newHeight) - это область относительно изображения, которую пользователь может нажать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...