Simple slider-like control that depicts its path as an arc using CoreAnimation layers. Supports both iOS and macOS platforms.
Like a slider, touch movements in the control change the value. For my implementation:
The above picture was taken from my SoundFonts iOS app where the knobs control various audio effects settings.
Included is a playground for playing with a knob.
minimumValue-- the lowest value that the control will report out.
maximumValue-- the highest value that the control will report out.
value-- the current value of the control (settable).
travelDistance-- the number of pixels to use in mouse/touch event distance calculations. By default this is the smaller of the frame width/height.
touchSensitivity-- scaling factor between touch movement and value change. The default is
1which means that one must drag 1x
travelDistancein order to change the value from
maximumValue; a value of
2would require 2x
maxChangeRegionWidthPercentage-- percentage of
travelDistancethat will always produce maximum value change. This defines a vertical region in the center of the view. Mouse/touch events outside of this region will have increased sensitivity as the event X is further from the view center X, requiring more movement for the same change in value.
trackLineWidth-- the line width of the knob's arc that is drawn from the current value to the end.
trackColor-- the color of the arc that is drawn from the current value to the end.
progressLineWidth-- the line width of the knob's arc that is drawn from the start to the current value.
progressColor-- the color of the arc thta is drawn from the start to the current value.
indicatorLineWidth-- the line width of the knob's indicator that is draw from the current value towards the knob center.
indicatorColor-- the color of the line that is drawn from the current value to the center.
indicatorLineLength-- the amount of the line that is drawn from the current value to the center, where 0.0 indicates no line will be drawn, and 0.5 results in a line that is half-way to the knob center point.
startAngle-- the starting point in radians of the arc (see below)
endAngle-- the ending point in radians of the arc
tickCount-- number of ticks to show
tickLineLength-- fraction of a radius to draw (0.0 - 1.0)
tickLineWidth-- width of the tick line
tickColor-- the color of the tick line
valueLabel-- an optional UILabel/NSText to use to show a formatted textual representation of the current value.
valueName-- optional name to show in the
valueLabelwhen the knob is not being manipulated. If
nil, the knob value is always shown.
valueFormatter-- optional NumberFormatter to use to generate the textual representation shown in the
valuePersistence-- the number of seconds to persist the last value shown before showing the
valueName(if non-nil). Only applies after the end of a mouse or touch event.
Arc angles are explained well in the UIBezierPath documentation. In brief, an angle of 0 will extend along the X axis, whereas an angle of π/2 will extend along the negative Y axis.
draw method used to render the knob's arc path draws in a clockwise fashion, so the end arc angle must be greater
than the start arc angle. The default values leave the opening in the arc path centered around the negative Y axis
(pointing down), with an arc distance of 2/16 of the circumference.
As one would expect, a touch in the knob's view area is tracked and any changes are reported to any registered actions:
touchSensitivityvalue that is used to generate updates to the control's
value, and the further away a touch moves horizontally from the center, the more sensitive the vertical movements become -- one must move larger vertical distances to achieve the same value change.
The package also includes a SwiftUI implementation:
KnobView. The defaults should be good enough to start with, but
there are modifiers you can apply to your KnobView to configure the look you want. The
KnobView constructor requires
two state bindings, one for the knob's value and another for the knob's manipulating flag. Additionally, you can provide
maximumValue values to override the defaults of 0.0 and 1.0 respectively.
KnobView(value: $volumeValue, manipulating: $volumeManipulating, minimum: 0.0, maximum: 1.0) .trackStyle(width: trackWidth, color: trackColor) .progressStyle(width: progressWidth, color: progressColor) .indicatorStyle(width: progressWidth, color: progressColor, length: 0.3)
KnobDemo folder contains an Xcode project which you can open to build simple demo apps for macOS and iOS
platforms. These also contain UI tests that make sure that the knobs properly track and report out their values.
The demo apps use SwiftUI for their view definitions. They both contain a
ContentView properly wires up two
instances with a
Text view that shows the value of a KnobView.