Как сгенерировать UIImages в шестиугольнике вида карты - PullRequest
0 голосов
/ 12 февраля 2019

Я создаю приложение, в котором я хочу отобразить профиль. Изображения людей "рядом с вами" в стиле улья с шестигранной головкой.

Полный улей должен быть перетаскиваемым, например, карты Google.

Мой вопрос заключается в том, можно ли это сделать с помощью UIKit, или было бы проще использовать UIKit и SpriteKit вместе.

Я надеюсь, что кто-то может указать мне правильное направление или получить какое-тоидеи о том, как это можно сделать.Спасибо за ваше время!

Обновление: Просто чтобы прояснить мой вопрос.

Вот так выглядит мой взгляд атм

И это то, чего я хочу достичь

На первом изображении я просто установил X и Y pos центральной середины UIImage.

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

1 Ответ

0 голосов
/ 12 февраля 2019
Только 1000 UIKit может сделать эту работу: вы должны попытаться настроить маску с помощью CALayer на UIImageView, например.

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

Для представлений шестиугольника вы найдете здесь интересный пример, который вы можете адаптировать для своего использования: http://sapandiwakar.in/make-hexagonal-view-on-ios/

Вот адаптация решения Sapan Diwakar в Swift 4.2 и использование расширений:

extension UIBezierPath {
    convenience init(roundedPolygonPathInRect rect: CGRect, lineWidth: CGFloat, sides: NSInteger, cornerRadius: CGFloat = 0, rotationOffset: CGFloat = 0) {
        self.init()

        let theta: CGFloat = 2.0 * CGFloat.pi / CGFloat(sides) // How much to turn at every corner
        let width = min(rect.size.width, rect.size.height)        // Width of the square

        let center = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + width / 2.0)

        // Radius of the circle that encircles the polygon
        // Notice that the radius is adjusted for the corners, that way the largest outer
        // dimension of the resulting shape is always exactly the width - linewidth
        let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0

        // Start drawing at a point, which by default is at the right hand edge
        // but can be offset
        var angle = CGFloat(rotationOffset)

        let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
        move(to: CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta)))

        for _ in 0 ..< sides {
            angle += theta

            let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
            let tip = CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle))
            let start = CGPoint(x: corner.x + cornerRadius * cos(angle - theta), y: corner.y + cornerRadius * sin(angle - theta))
            let end = CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta))

            addLine(to: start)
            addQuadCurve(to: end, controlPoint: tip)
        }

        close()
    }
}

extension UIImageView {
    func setupHexagonMask(lineWidth: CGFloat, color: UIColor, cornerRadius: CGFloat) {
        let path = UIBezierPath(roundedPolygonPathInRect: bounds, lineWidth: lineWidth, sides: 6, cornerRadius: cornerRadius, rotationOffset: CGFloat.pi / 2.0).cgPath

        let mask = CAShapeLayer()
        mask.path = path
        mask.lineWidth = lineWidth
        mask.strokeColor = UIColor.clear.cgColor
        mask.fillColor = UIColor.white.cgColor
        layer.mask = mask

        let border = CAShapeLayer()
        border.path = path
        border.lineWidth = lineWidth
        border.strokeColor = color.cgColor
        border.fillColor = UIColor.clear.cgColor
        layer.addSublayer(border)
    }
}

И тогда вы можете просто использовать его так:

let image = UIImageView(frame: CGRect(x: 30, y: 30, width: 300, height: 300))
image.contentMode = .scaleAspectFill
image.image = UIImage(named: "lenna.png")
image.setupHexagonMask(lineWidth: 5.0, color: .white, cornerRadius: 20.0)

view.addSubview(image)

РЕДАКТИРОВАТЬ : Как я уже говорил, самый простой способ - это использовать UIScrollView для отображения вашей карты, и с помощью простой математики вы можете отображать свои шестиугольники так, как вы хотите.

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

Example with the same image, here lenna.png

Предполагая, что view является UIScrollView:

let hexaDiameter : CGFloat = 150
let hexaWidth = hexaDiameter * sqrt(3) * 0.5
let hexaWidthDelta = (hexaDiameter - hexaWidth) * 0.5
let hexaHeightDelta = hexaDiameter * 0.25
let spacing : CGFloat = 5

let rows = 10
let firstRowColumns = 6

view.contentSize = CGSize(width: spacing + CGFloat(firstRowColumns) * (hexaWidth + spacing),
                          height: spacing + CGFloat(rows) * (hexaDiameter - hexaHeightDelta + spacing) + hexaHeightDelta)

for y in 0..<rows {
    let cellsInRow = y % 2 == 0 ? firstRowColumns : firstRowColumns - 1
    let rowXDelta = y % 2 == 0 ? 0.0 : (hexaWidth + spacing) * 0.5
    for x in 0..<cellsInRow {
        let image = UIImageView(frame: CGRect(x: rowXDelta + CGFloat(x) * (hexaWidth + spacing) + spacing - hexaWidthDelta,
                                              y: CGFloat(y) * (hexaDiameter - hexaHeightDelta + spacing) + spacing,
                                              width: hexaDiameter,
                                              height: hexaDiameter))
        image.contentMode = .scaleAspectFill
        image.image = UIImage(named: "lenna.png")
        image.setupHexagonMask(lineWidth: 5.0, color: .white, cornerRadius: 10.0)
        view.addSubview(image)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...