iOS 绘制就是采集点,贝塞尔曲线得到形状,绘图上下文去渲染出来
Asana/Drawsana 图形库,设计的挺好
他可以画多种图形,画线、文本、橡皮擦、五角形、矩形、箭头、角度,
他支持多种操作,撤销上一步、还原上一步,平移选择的已渲染图形
他的实现,大量使用了协议
设计: 主要看数据结构
可以分为三个层次,行为的处理 ( 采集点的传递 ) ,图形的绘制, 呈现的视图( 最开始采集点, 最后的渲染呈现 )
图形的绘制
Shape 协议,决定了可看 ( 可渲染 ),可点击
ShapeSelectable 协议,增加了形状区域和仿射变换。
最基础的形状,Shape
有一个 id、 类型的区分,
渲染出来,可否响应点击事件,
更改绘图设置 ( 画线的颜色、画线的填充色、画线的宽度 )
public protocol Shape: AnyObject, Codable {
var id: String { get set }
static var type: String { get }
func render(in context: CGContext)
func hitTest(point: CGPoint) -> Bool
func apply(userSettings: UserSettings)
}
通用的形状协议 ShapeSelectable
下面 3 个协议,添加功能
ShapeWithBoundingRect 协议继承自 Shape, 添加了区域
public protocol ShapeWithBoundingRect: Shape {
var boundingRect: CGRect { get }
}
ShapeWithTransform 协议继承自 Shape, 添加了仿射变换
public protocol ShapeWithTransform: Shape {
var transform: ShapeTransform { get set }
}
最终形状通用的协议为 ShapeSelectable
,
他继承自上面两个协议
public protocol ShapeSelectable: ShapeWithBoundingRect, ShapeWithTransform {
}
具体的形状,以角度形状为例 AngleShape
角度这个形状,需要三个点确定
class AngleShape: ShapeSelectable{
public var a: CGPoint = .zero
public var b: CGPoint = .zero
public var c: CGPoint = .zero
// ...
// 实现通用的形状信息, id 、种类、线宽等
}
这里还有一个协议, ShapeWithThreePoints
该协议拿到了三个点,可算出三个点决定的矩形区域
extension AngleShape: ShapeWithThreePoints{}
public protocol ShapeWithThreePoints {
var a: CGPoint { get set }
var b: CGPoint { get set }
var c: CGPoint { get set }
var strokeWidth: CGFloat { get set }
}
ShapeWithThreePoints
三点形状协议,统一处理了三个点形状的区域;
这个库的形状,大部分是 ShapeWithTwoPoints
, 2 点形状协议,统一处理了 2 点形状的区域,
椭圆、星星、矩形、线段,都是 2 点形状
行为的处理,这个库是 tool
工具 tool 是形状 shape 的进一步