Рисование кругов в рандомном месте

swift
xcode
ios

#1

Ребят подскажите кто может. Вопрос в следующем: 1.Нужно реализовать чтобы на экране появлялись круги в рандомном месте. 2.Разных радиусов и не перекрывали друг друга.

При компиляции почему то отображается только один круг.

Создал отдельный файл для View. Вот код который я сотворил:

override func draw(_ rect: CGRect) {

var number = 1

while number <= 5 {
    //1. Координаты центра экрана
    let viewMidX = self.bounds.size.height
    let viewMidY = self.bounds.size.width

    //2. Радиус уруга
    let circleWidth = CGFloat(20 + arc4random_uniform(30))
    let circleHeight = circleWidth

    //3. Два рандомных числа
    let randomNumberOne = CGFloat(arc4random_uniform(40))
    let randomNumberTwo = CGFloat(arc4random_uniform(20))

    //4. Координаты и размеры круга
    let rect = CGRect(x: viewMidX / 3 + randomNumberOne , y: viewMidY / 3 + randomNumberTwo , width: circleWidth, height: circleHeight)

    /**5.
     roundedRect: границы в пределах которых отрисовывает;
     cornerRadius: скгругление углов;
     **/
    let circlePath = UIBezierPath(roundedRect: rect, cornerRadius: circleWidth / 2)

    //5. Цвет заливки внутренний круга
    мойЦвет.setFill()
    circlePath.fill()

    //6. Цвет обводки круга
    мойЦвет.setStroke()
    circlePath.stroke()

    number += 1
}

В файле ViewController я делаю этому кругу некоторую анимацию(пульсирует)
override func viewDidLoad() {
super.viewDidLoad()

//7.
self.view.transform = CGAffineTransform(scaleX: 1, y: 1)

//8. Анимация круга и его пульсация
UIView.animateKeyframes(withDuration: 1, delay: 0, options: [.autoreverse, .repeat], animations: {
    self.view.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
}) { finished in
}

}


#2

var number = 2 ???


#3

Не не я изменил на 5, все равно 1 круг


#4

тогда так while number <= 5 {


#5

Мне стало интересно реализовать это, и я расширил UIView:

extension UIView {
func isCrossing(_ view: UIView) -> Bool {
    let firstParams = (midX: Float(self.frame.midX), midY: Float(self.frame.midY), radius: Float(self.frame.width/2))
    let secondParams = (midX: Float(view.frame.midX), midY: Float(view.frame.midY), radius: Float(view.frame.width/2))
    let distance = (firstParams.midX - secondParams.midX, firstParams.midY - secondParams.midY)
    let hypotenuse = sqrtf(powf(distance.0, 2) + powf(distance.1, 2))
    return hypotenuse - (firstParams.radius + secondParams.radius) <= 0 ? true : false
    }
}

Функция, вроде, работает правильно, но предназначена только для сравнения окружностей.

Дальше я, немного переписав вашу функцию, создал класс, который рисует эти круги:

class RedCircle {
func drawCircles() -> [UIView] {
    var number = 1
    var viewsArray: [UIView] = []
    
    //1. Ширина и высота экрана
    let viewHeight = UIScreen.main.bounds.size.height
    let viewWidth = UIScreen.main.bounds.size.width
    
    while number <= 5 {
        //2. Радиус круга
        let maxRadius: CGFloat = 100
        let rectSideSize = CGFloat.random(in: 5...maxRadius)//CGFloat(20 + arc4random_uniform(30))
        
        //3. Два рандомных числа
        let randomNumberOne = CGFloat.random(in: 0...viewWidth-maxRadius)//CGFloat(arc4random_uniform(40))
        let randomNumberTwo = CGFloat.random(in: 0...viewHeight-maxRadius)//CGFloat(arc4random_uniform(20))
        
        //4. Координаты и размеры круга
        let rect = CGRect(x: /*viewMidX / 3 +*/ randomNumberOne , y: /*viewMidY / 3 +*/ randomNumberTwo , width: rectSideSize, height: rectSideSize)
        
        //5. Смотрим пересечение
        let newView = UIView(frame: rect)
        guard (viewsArray.filter { $0.isCrossing(newView) }).isEmpty else { print(false); continue }
        
        //6. Задаём цвет и делаем обрезку
        newView.layer.cornerRadius = circleRadius/2
        newView.layer.masksToBounds = true
        newView.backgroundColor = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)
        
        //7. Добавляем в массив
        viewsArray.append(newView)
        number += 1
        
    }
    return viewsArray
}

Во viewController:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let viewsArray = RedCircle().drawCircles()
    for circleView in viewsArray {
        self.view.addSubview(circleView)
    }
    UIView.animateKeyframes(withDuration: 1, delay: 0, options: [.autoreverse, .repeat], animations: {
        viewsArray.forEach { $0.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) }
    })
}

#6

Сейчас буду смотреть Спасибо за ответ.


#7

Higderin вы не подскажете еще один вопрос? Я хочу также добавить в центр каждого круга надпись. Я добавляю следующий код в тело цикла:

    let sizeText: CGFloat = 55.0
    let numberRandomLabel = UILabel(frame: CGRect(x: randomNumberOne, y: randomNumberTwo, width: 100, height: 40))
    
    numberRandomLabel.text = "TTT"
    numberRandomLabel.textColor = UIColor.black
    numberRandomLabel.textAlignment = .center
    
    numberRandomLabel.font = UIFont.systemFont(ofSize: 20.0)
    numberRandomLabel.translatesAutoresizingMaskIntoConstraints = false

Но у меня ничего отрисовывается.


#8

текст рисуется через CATextLayer()

private func drawTextLayer() {
        let offset: CGFloat = radius3 * 0.1
        let scale = UIScreen.main.scale
        let textFontSize = ceil(radius3 * 1.0)
        let text = String(describing: model.painLevel!)
        var textPoint: CGPoint
        
        let font = UIFont.robotoBoldFontOfSize(ofSize: textFontSize)
        textSize = text.sizeOfString(usingFont: font)
        
        if textLayer == nil {
            textLayer = CATextLayer()
            
            layer.addSublayer(textLayer)
        }
        
        if model.painTrend! == 0 || !showTriangle {
            textPoint = CGPoint(x: viewCenter.x - textSize.width / 2, y: viewCenter.y - textSize.height / 2)
        }
        else if model.painTrend! > 0 {
            textPoint = CGPoint(x: viewCenter.x - textSize.width / 2, y: viewCenter.y - textSize.height / 2 - (radius3 - textSize.height) / 2 + offset)
        }
        else {
            textPoint = CGPoint(x: viewCenter.x - textSize.width / 2, y: viewCenter.y - textSize.height - (radius3 - textSize.height) / 2 + offset)
        }
        
        textLayer.string = text
        textLayer.foregroundColor = UIColor.white.cgColor
        textLayer.font = font
        textLayer.fontSize = textFontSize
        textLayer.alignmentMode = kCAAlignmentCenter
        textLayer.backgroundColor = UIColor.clear.cgColor
        textLayer.contentsScale = scale
        textLayer.frame = CGRect(origin: textPoint, size: textSize)
    }

#9

Ребят, хочу кое что изменить. Добавляю navigationBar. Мне нужно ограничить view, чтобы круги не рисовались в области под navigationBar. Как можно это сделать?

Я использую в методе draw

    let viewHeight = self.view.frame.size.height
    let viewWidth = self.view.frame.size.width

Мне нужно как то учесть высоту navigationBar. Нашел чему равна эта величина…

 let navBar = navigationController?.navigationBar.frame.size.height

но как ограничить View?


#10

а не проще view в котором рисуете, расположить после navigationBara? т.е. topConstraint для view 0 относительно navigationBara


#11

Ещё можно минимум рандомного числа, отвечающего за “y”, ограничивать navBar:
let randomNumberTwo = CGFloat.random(in: navBar...viewHeight-maxRadius)