如何解决确定自定义iOS视图是否重叠
我已经定义了一个CircleView
类:
class CircleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.clear
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
// Get the Graphics Context
if let context = UIGraphicsGetCurrentContext() {
// Set the circle outerline-width
context.setlinewidth(5.0);
// Set the circle outerline-colour
UIColor.blue.set()
// Create Circle
let center = CGPoint(x: frame.size.width/2,y: frame.size.height/2)
let radius = (frame.size.width - 10)/2
context.addArc(center: center,radius: radius,startAngle: 0.0,endAngle: .pi * 2.0,clockwise: true)
context.setFillColor(UIColor.blue.cgColor)
// Draw
context.strokePath()
context.fillPath()
}
}
}
var numberOfCircles: Int!
var circles: [CircleView] = []
numberOfCircles = Int.random(in: 1..<10)
let circleWidth = CGFloat(50)
let circleHeight = circleWidth
var i = 0
while i < numberOfCircles {
let circleView = CircleView(frame: CGRect(x: 0.0,y: 0.0,width: circleWidth,height: circleHeight))
circles.append(circleView)
i += 1
}
创建圆后,我调用一个函数drawCircles
,它将在屏幕上绘制它们:
func drawCircles(){
for c in circles {
c.frame.origin = c.frame.randomPoint
while !UIScreen.main.bounds.contains(c.frame.origin) {
c.frame.origin = CGPoint()
c.frame.origin = c.frame.randomPoint
let prev = circles.before(c)
if prev?.frame.intersects(c.frame) == true {
c.frame.origin = c.frame.randomPoint
}
}
}
for c in circles {
self.view.addSubview(c)
}
}
while
方法中的drawCircles
循环可确保没有任何圆放置在屏幕边界之外,并且可以按预期工作。
我正在努力确保彼此之间不重叠,就像这样:
extension BidirectionalCollection where Iterator.Element: Equatable {
typealias Element = Self.Iterator.Element
func after(_ item: Element,loop: Bool = false) -> Element? {
if let itemIndex = self.firstIndex(of: item) {
let lastItem: Bool = (index(after:itemIndex) == endindex)
if loop && lastItem {
return self.first
} else if lastItem {
return nil
} else {
return self[index(after:itemIndex)]
}
}
return nil
}
func before(_ item: Element,loop: Bool = false) -> Element? {
if let itemIndex = self.firstIndex(of: item) {
let firstItem: Bool = (itemIndex == startIndex)
if loop && firstItem {
return self.last
} else if firstItem {
return nil
} else {
return self[index(before:itemIndex)]
}
}
return nil
}
}
这是if语句;似乎没有按照我的意愿去做;这是为了确保如果一个圆与另一个圆相交,请将其原点更改为新的东西:
if prev?.frame.intersects(c.frame) == true {
c.frame.origin = c.frame.randomPoint
}
如果任何人对逻辑可能存在的任何想法,或关于如何确保圆圈彼此不重叠的其他想法,那将是有帮助的!
编辑:我确实尝试了Eugene这样回答的建议,但仍然得到了相同的结果:
func distance(_ a: CGPoint,_ b: CGPoint) -> CGFloat {
let xdist = a.x - b.x
let ydist = a.y - b.y
return CGFloat(sqrt(xdist * xdist + ydist * ydist))
}
if prev != nil {
if distance((prev?.frame.origin)!,c.frame.origin) <= 40 {
print("2")
c.frame.origin = CGPoint()
c.frame.origin = c.frame.randomPoint
}
}
但结果仍然相同
编辑2
根据Eugene编辑的答案/说明修改了我的for循环;仍然有圆圈重叠的问题:
对于圈子中的c { c.frame.origin = c.frame.randomPoint
let prev = circles.before(c)
let viewMidX = self.circlesView.bounds.midX
let viewMidY = self.circlesView.bounds.midY
let xPosition = self.circlesView.frame.midX - viewMidX + CGFloat(arc4random_uniform(UInt32(viewMidX*2)))
let yPosition = self.circlesView.frame.midY - viewMidY + CGFloat(arc4random_uniform(UInt32(viewMidY*2)))
if let prev = prev {
if distance(prev.center,c.center) <= 50 {
c.center = CGPoint(x: xPosition,y: yPosition)
}
}
}
解决方法
这纯粹是几何挑战。只要确保圆心之间的距离大于或等于其半径之和即可。
编辑1
使用UIView.center
代替UIView.frame.origin
。 UIView.frame.origin
为您提供UIView
的左上角。
if let prev = prev {
if distance(prev.center,c.center) <= 50 {
print("2")
c.center = ...
}
}
编辑3
func distance(_ a: CGPoint,_ b: CGPoint) -> CGFloat {
let xDist = a.x - b.x
let yDist = a.y - b.y
return CGFloat(hypot(xDist,yDist))
}
let prev = circles.before(c)
if let prevCircleCenter = prev?.center {
let distance = distance(prevCenter,c.center)
if distance <= 50 {
let viewMidX = c.bounds.midX
let viewMidY = c.bounds.midY
var newCenter = c.center
var centersVector = CGVector(dx: newCenter.x - prevCircleCenter.x,dy: newCenter.y - prevCircleCenter.y)
centersVector.dx *= 51 / distance
centersVector.dy *= 51 / distance
newCenter.x = prevCircleCenter.x + centersVector.dx
newCenter.y = prevCircleCenter.y + centersVector.dy
c.center = newCenter
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。