Rumor has it that Apple will support the Apple Pencil in the forthcoming iPad. If so, more developers will want to use the new features of UITouch
-- force, angle, and elevation -- supported by the incredibly-precise stylus.
Basically, it's trivial:
-- Force is UITouch.Force
;
-- Angle is UITouch.GetAzimuthAngle(UIView)
; and
-- Angle above horizontal is UITouch.AltitudeAngle
(The UIView
objects are there, I think, to make it easier to create a custom angular transform that is more natural to the task at hand -- i.e., an artist could "rotate" the page slightly to accommodate the angle with which they like to work. I think.)
Anyhow, here's some code:
[code lang="fsharp"]
namespace UITouch0
open System
open UIKit
open Foundation
open System.Drawing
open CoreGraphics
type ContentView(color : UIColor) as this =
inherit UIView()
do this.BackgroundColor \<- color
let MaxRadius = 200.0
let MaxStrokeWidth = nfloat 10.0
//Mutable!
member val Circle : (CGPoint * nfloat * nfloat * nfloat ) option = None with get, set
member this.DrawTouch (touch : UITouch) =
let radius = (1.0 - (float touch.AltitudeAngle) / (Math.PI / 2.0)) * MaxRadius |> nfloat
this.Circle \<- Some (touch.LocationInView(this), radius, touch.GetAzimuthAngle(this), touch.Force)
this.SetNeedsDisplay()
override this.Draw rect =
match this.Circle with
| Some (location, radius, angle, force) ->
let rectUL = new CGPoint(location.X - radius, location.Y - radius)
let rectSize = new CGSize(radius * (nfloat 2.0), radius * (nfloat 2.0))
use g = UIGraphics.GetCurrentContext()
let strokeWidth = force * MaxStrokeWidth
g.SetLineWidth(strokeWidth)
let hue = angle / nfloat (Math.PI * 2.0)
let color = UIColor.FromHSB(hue, nfloat 1.0, nfloat 1.0)
g.SetStrokeColor(color.CGColor)
g.AddEllipseInRect \<| new CGRect(rectUL, rectSize)
g.MoveTo (location.X, location.Y)
let endX = location.X + nfloat (cos(float angle)) * radius
let endY = location.Y + nfloat (sin(float angle)) * radius
g.AddLineToPoint (endX, endY)
g.StrokePath()
| None -> ignore()
type SimpleController() =
inherit UIViewController()
override this.ViewDidLoad() =
this.View \<- new ContentView(UIColor.Blue)
override this.TouchesBegan(touches, evt) =
let cv = this.View :?> ContentView
touches |> Seq.map (fun o -> o :?> UITouch) |> Seq.iter cv.DrawTouch
override this.TouchesMoved(touches, evt) =
let cv = this.View :?> ContentView
touches |> Seq.map (fun o -> o :?> UITouch) |> Seq.iter cv.DrawTouch
[\<Register("AppDelegate")>]
type AppDelegate() =
inherit UIApplicationDelegate()
let window = new UIWindow(UIScreen.MainScreen.Bounds)
override this.FinishedLaunching(app, options) =
let viewController = new SimpleController()
viewController.Title \<- "F# Rocks"
let navController = new UINavigationController(viewController)
window.RootViewController \<- navController
window.MakeKeyAndVisible()
true
module Main =
[\<EntryPoint>]
let main args =
UIApplication.Main(args, null, "AppDelegate")
0
[/code]
And it looks like this:
[video width="600" height="800" mp4="/uploads/2016/03/ScreenFlow-2.mp4"][/video]