Skip to content

Instantly share code, notes, and snippets.

@romainmenke
Last active December 13, 2015 22:08
Show Gist options
  • Save romainmenke/14a52b61d7e91cb3bcdc to your computer and use it in GitHub Desktop.
Save romainmenke/14a52b61d7e91cb3bcdc to your computer and use it in GitHub Desktop.
import UIKit
import XCPlayground
extension UIView {
var diagonal : CGFloat {
return sqrt(pow(self.frame.width, 2) + pow(self.frame.height, 2))
}
var radius : CGFloat {
return diagonal / 2
}
}
extension CGPoint {
func getPoint(atDistance distance: CGFloat, overAngleRadians angle:CGFloat) -> CGPoint {
let x = self.x
let y = self.y
let dx = (distance * cos(angle))
let dy = (distance * sin(angle))
return CGPoint(x: (dx + x), y: (dy + y))
}
}
protocol Planet {
var center : CGPoint { get }
var superview : UIView? { get }
var radius : CGFloat { get }
func convertPoint(point: CGPoint, toView: UIView?) -> CGPoint
}
extension Planet {
private func encirclePoint(point : CGPoint, distance:CGFloat, inParts parts: Int) -> [CGPoint] {
let angle = 2 * CGFloat(M_PI) / CGFloat(parts) // critical part, you need radians for trigonometry
var runningAngle : CGFloat = (CGFloat(M_PI) / 2) * (-1) // start at the top, change the multiplier to adjust, -1 is top
var points : [CGPoint] = []
for _ in 0..<parts {
let circlePoint = point.getPoint(atDistance: distance, overAngleRadians: runningAngle)
points.append(circlePoint)
runningAngle += angle
}
return points
}
func encircle(withViews satellites : [UIView], withMargin margin : CGFloat) {
guard !(satellites.isEmpty) else { // if there are no subviews : abort
return
}
let distance = radius + margin
var supercenter = CGPointZero
if let satelliteSuperview = satellites.first?.superview, let superview = superview where satelliteSuperview != superview { // this expects all satellites to have the same superview
supercenter = convertPoint(center, toView: satelliteSuperview)
} else {
supercenter = center
}
let points = encirclePoint(supercenter, distance: distance, inParts: satellites.count)
guard satellites.count == points.count else { // if the count is not the same : abort
return
}
for (point, satellite) in zip(points,satellites) { satellite.center = point }
}
}
// tests
class PlanetView : UIView, Planet { }
let view : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
view.backgroundColor = UIColor.blackColor()
let planet = PlanetView(frame: CGRect(x: 115, y: 100, width: 200, height: 200))
planet.backgroundColor = UIColor(red: 0.0, green: 0.3, blue: 1.0, alpha: 1.0)
planet.layer.cornerRadius = planet.frame.height / 2
view.addSubview(planet)
let satFrame = CGRect(x: 0, y: 0, width: 25, height: 25)
let satOne = UIView(frame: satFrame)
let satTwo = UIView(frame: satFrame)
let satThree = UIView(frame: satFrame)
let satFour = UIView(frame: satFrame)
let satFive = UIView(frame: satFrame)
let satSix = UIView(frame: satFrame)
satOne.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
satTwo.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.6)
satThree.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.6)
satFour.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.6)
satFive.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.6)
satSix.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.6)
satOne.layer.cornerRadius = satFrame.height / 2
satTwo.layer.cornerRadius = satFrame.height / 2
satThree.layer.cornerRadius = satFrame.height / 2
satFour.layer.cornerRadius = satFrame.height / 2
satFive.layer.cornerRadius = satFrame.height / 2
satSix.layer.cornerRadius = satFrame.height / 2
view.addSubview(satOne)
view.addSubview(satTwo)
view.addSubview(satThree)
view.addSubview(satFour)
view.addSubview(satFive)
//view.addSubview(satSix)
planet.encircle(withViews: [satOne,satTwo,satThree,satFour,satFive], withMargin: 25)
XCPlaygroundPage.currentPage.liveView = view
@romainmenke
Copy link
Author

screen shot 2015-12-13 at 19 19 27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment