Swift实现带10个以上控制点可调整为任意形状的圆形绘制方案
需求说明
我想要实现具备10个以上控制点、可调整为任意形状的圆形效果,需使用Swift语言完成开发。我已经找到Javascript实现的类似效果,但不知道如何迁移到Swift平台开发。我也尝试过使用Bezier path进行实现,现有代码如下,但不知道如何完成后续开发:
现有代码
自定义贝塞尔路径视图类
class MyBezierPathView: UIView { private var path: UIBezierPath? // 起点 var startP = CGPoint.zero // 终点 var endP = CGPoint.zero // 控制点 var controlP = CGPoint.zero var pathColor: UIColor? var pathWidth: CGFloat = 0.0 // 当前被触摸的点标识 private var currentTouchP = 0 // 初始化 override init(frame: CGRect) { super.init(frame: frame) } // 绘制贝塞尔路径 override func draw(_ rect: CGRect) { path = UIBezierPath() path?.move(to: startP) path?.addQuadCurve(to: endP, controlPoint: controlP) path?.lineWidth = pathWidth pathColor?.setStroke() path?.stroke() path = UIBezierPath() path?.lineWidth = 1 UIColor.gray.setStroke() let lengths: [CGFloat] = [5] path?.setLineDash(lengths, count: 1, phase: 1) path?.move(to: controlP) path?.addLine(to: startP) path?.stroke() path?.move(to: controlP) path?.addLine(to: endP) path?.stroke() path = UIBezierPath(arcCenter: startP, radius: 4, startAngle: 0, endAngle: .pi * 2, clockwise: true) UIColor.black.setStroke() path?.fill() path = UIBezierPath(arcCenter: endP, radius: 4, startAngle: 0, endAngle: .pi * 2, clockwise: true) UIColor.black.setStroke() path?.fill() path = UIBezierPath(arcCenter: controlP, radius: 3, startAngle: 0, endAngle: .pi * 2, clockwise: true) path?.lineWidth = 2 UIColor.black.setStroke() path?.stroke() let startMsgRect = CGRect(x: startP.x + 8, y: startP.y - 7, width: 50, height: 20) "start point".draw(in: startMsgRect, withAttributes: nil) let endMsgRect = CGRect(x: endP.x + 8, y: endP.y - 7, width: 50, height: 20) "end point".draw(in: endMsgRect, withAttributes: nil) let control1MsgRect = CGRect(x: controlP.x + 8, y: controlP.y - 7, width: 50, height: 20) "control point".draw(in: control1MsgRect, withAttributes: nil) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let startPoint = touches.first?.location(in: self) let startR = CGRect(x: startP.x - 4, y: startP.y - 4, width: 80, height: 80) let endR = CGRect(x: endP.x - 4, y: endP.y - 4, width: 80, height: 80) let controlR = CGRect(x: controlP.x - 4, y: controlP.y - 4, width: 80, height: 80) guard let startPoint = startPoint else { print("startPoint is nil.") return } if startR.contains(startPoint) { currentTouchP = 1 } else if endR.contains(startPoint) { currentTouchP = 2 } else if controlR.contains(startPoint) { currentTouchP = 3 } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { var touchPoint = touches.first?.location(in: self) if touchPoint!.x < 0 { touchPoint!.x = 0 } if touchPoint!.x > bounds.size.width { touchPoint!.x = bounds.size.width } if touchPoint!.y < 0 { touchPoint!.y = 0 } if touchPoint!.y > bounds.size.height { touchPoint!.y = bounds.size.height } switch currentTouchP { case 1: startP = touchPoint! case 2: endP = touchPoint! case 3: controlP = touchPoint! default: break } setNeedsDisplay() } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { currentTouchP = 0 } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { touchesEnded(touches, with: event) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
视图控制器类
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let frame = CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height) let pathView = MyBezierPathView(frame: frame) pathView.startP = CGPoint(x: 110, y: 150) pathView.endP = CGPoint(x: 258.47, y: 211.53) pathView.controlP = CGPoint(x: 196.94, y: 150) pathView.pathColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 1) pathView.pathWidth = 2 pathView.backgroundColor = UIColor.white pathView.layer.borderWidth = 1 view.addSubview(pathView) } }
内容的提问来源于stack exchange,提问作者Nick Wen
相关产品推荐
相关产品推荐

