Theory
There's no way around it, next year is going to be all about thinking in terms of time. The Apple Watch and the accompanying WatchKit that is soon to be released to developers will bring with it new ways of visualising and portraying time. And although the watch itself isn't round, the circular aesthetic is tightly linked to our ideas of what a watch is. Hence the Apple Watch interface has its fair share of circles. These not only fulfil the requirement of watchness but also provide a sense of space around objects and icons that are close together.The opportunities for scaling and rotating circles are vast. As we've seen from early demonstrations of the Apple Watch, circles can grow and shrink, shift and rotate. Once circles become part of an interactive interface, squares and rectangles start to appear rather limited and like they've been hogging all the space for far too long.
Was it in part the dream of 3D interfaces, which have been largely centred on rectangles, that delayed the age of the circle? Or the lack of serious space restrictions prior to the smartwatch? Whatever the reason, the flatness and scaling back and removal of features like Cover Flow have left the gate wide open for innovative 2D interfaces.
This doesn't discount future 3D innovations, but it does demonstrate that there's more to life than rectangles and that future UIs will be unlikely to ignore the importance of the circle.
Practice: Polygons
One of the first things to crack are regular polygons. A watch face, for example, relies on the positioning of numbers at regular intervals and it is by placing a polygon within a circle that we can make these divisions. In this example the 12, 3, 6 and 9 are pinpointed (note: all examples are written in JavaScript and HTML5, if you have JS switched off or are using an older browser you won't see anything):
Code: In Swift
In Swift, circles are a trivial thing to achieve using UIBezierPath:
UIBezierPath(ovalInRect: CGRect(x: 100,y: 100,width: 100,height: 100))Polygons are slightly trickier but given a bit of trigonometry (and a little assistance from here and here) it is possible to throw together some rough and ready code to make regular polygons with any number of sides happen:
func degree2radian(a:Double)->Double {return M_PI * a/180 } func polygon(sides:Int,x:Double,y:Double,radius:Double)->[CGPoint] { var angle = degree2radian(360/Double(sides)) var cx:Double = x // x origin var cy:Double = y // y origin var r:Double = radius // radius of circle var i=0 var points = [CGPoint]() while i <= sides { var xpo = cx + r * cos(angle * Double(i)) var ypo = cy + r * sin(angle * Double(i)) points.append(CGPoint(x: xpo, y: ypo)) i++; } return points } var points = polygon(12,100,100,500) var cpg = points[0] var bpg = UIBezierPath() bpg.moveToPoint(cpg) for p in points { bpg.addLineToPoint(p) } bpgThese examples are written for a Playground where clicking on the plus icon in the preview will display the shapes. I'll move on to drawing in a UIView in a later post but to get a feel for how to distribute numbers around a clock face using polygons in Xcode here's an example that you can copy and paste into the viewDidLoad of your initial UIViewController:
// create function to covert degrees to radians, necessary for use of cos() and sin() func degree2radian(a:Double)->Double { return M_PI * a/180 } // creates the points of the polygon func polygon(sides:Int,x:Double,y:Double,radius:Double)->[CGPoint] { let angle = degree2radian(360/Double(sides)) let cx:Double = x // x origin let cy:Double = y // y origin let r:Double = radius // radius of circle var i=0 var points = [CGPoint]() while i <= sides { let xpo = cx + r * cos(angle * (Double(i)+(Double(sides)/4*3))) let ypo = cy + r * sin(angle * (Double(i)+(Double(sides)/4*3))) // add (Double(sides)/4*3) to multiplication to ensure that index twelve corresponds to the twelve position, it will also ensure that minutes and seconds are correctly distributed points.append(CGPoint(x: xpo, y: ypo)) i++; } return points } // get the array of points along the polygon var points = polygon(12,Double(CGRectGetMidX(self.view.frame)),Double(CGRectGetMidY(self.view.frame)),100) // add a label at each point of the polygon for p in enumerate(points) { if p.index >= 1 { // I don't want to include zero in the numbers let a = UILabel(frame: CGRect(origin: p.element, size: CGSize(width: 20, height: 20))) a.text = String(p.index) self.view.addSubview(a); } }What you should see when you build and run is something like this:
And that's where I'll not only finish for now, but also where I'll start from in the next post.
Note: in this post I update the polygon code to work consistently using CGFloat for layout purposes on 32-bit devices.
'Design Principles: Visual Perception And The Principles Of Gestalt' (Smashing Magazine)
'Why Rounded Corners are Easier on the Eyes' (uxmovement)
'Smartwatch UI Design: A Battle of Circles and Squares' (Sitepoint)
'How do rounded corners affect usability?' (ux.stackexchange.com)
'Humans Prefer Curved Visual Objects' (Moshe Bar and Maital Neta, Psychological Science [PDF])
'playing with ellipse in swift Part.2' (gracefullycoded.com)
Note: in this post I update the polygon code to work consistently using CGFloat for layout purposes on 32-bit devices.
Further reading (Design and UI-based)
'Beyond the Apple Watch: 4 Features Show Direction of UX' (HOW)'Design Principles: Visual Perception And The Principles Of Gestalt' (Smashing Magazine)
'Why Rounded Corners are Easier on the Eyes' (uxmovement)
'Smartwatch UI Design: A Battle of Circles and Squares' (Sitepoint)
'How do rounded corners affect usability?' (ux.stackexchange.com)
'Humans Prefer Curved Visual Objects' (Moshe Bar and Maital Neta, Psychological Science [PDF])
Further reading (code-based)
'playing with ellipse in Swift part.1' (gracefullycoded.com)'playing with ellipse in swift Part.2' (gracefullycoded.com)
Comments
Post a Comment