【问题标题】:How to draw same bezier path multiple times after finished the previous one?完成上一条后如何多次绘制相同的贝塞尔路径?
【发布时间】:2021-04-14 12:53:34
【问题描述】:

我正在使用贝塞尔路径、形状图层和 CABasicAnimation 来动画地绘制视图。但它只绘制一次视图。完成上一条后如何多次绘制相同的贝塞尔路径?

这是用于创建此类波形的附加代码。请检查...

类视图控制器:UIViewController {

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var graphView: UIView!

// MARK:- PROPERTIES
var movingPoint: CGFloat = 0.0
var startInterval: CGFloat = 10.0
var noOfIntervals: CGFloat = 0
var intervalWidth: CGFloat = 0
var pWaveWidth: CGFloat = 20.0
var qrsWaveWidth: CGFloat = 15
var tWaveWidth: CGFloat = 30
var gapBetweenTwoIntervals: CGFloat = 50
let shapeLayer = CAShapeLayer()
var bezierPath = UIBezierPath()
let animation = CABasicAnimation(keyPath: "strokeEnd")



override func viewDidLoad() {
    super.viewDidLoad()
    
    graphView.translatesAutoresizingMaskIntoConstraints = true
    graphView.frame.size = CGSize(width: 100000, height: 150)
    DispatchQueue.main.async {
        self.graphView.layoutIfNeeded()
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    createGraph()
}


@objc func createGraph() {
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.lineWidth = 2.0
    _ = createBezierPath()
    graphView.layer.addSublayer(shapeLayer)
}

@discardableResult
@objc func createBezierPath(isPathAlreadyCreated: Bool = false) -> UIBezierPath {
    
    for _ in 0..<205 {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: movingPoint, y: graphView.halfHeight))
        path.addLine(to: CGPoint(x: startInterval, y: graphView.halfHeight))
        
        // P Point Curve
        let pWaveX = startInterval + pWaveWidth
        path.addQuadCurve(to: CGPoint(x: pWaveX, y: graphView.halfHeight), controlPoint: CGPoint(x: pWaveX - 6.0, y: graphView.halfHeight - 30.0))
        
        let gapBetweenPAndQRS: CGFloat = 20.0
        path.addLine(to: CGPoint(x: (pWaveX + gapBetweenPAndQRS), y: graphView.halfHeight))
        
        // QRS
        let qrsStartPoint = pWaveX + gapBetweenPAndQRS
        let qrsComplex = qrsStartPoint + qrsWaveWidth
        let qrsComplexEndPoint = qrsComplex + (qrsWaveWidth / 2)
        path.addLine(to: CGPoint(x: qrsStartPoint + (qrsWaveWidth / 2), y: graphView.halfHeight - 70.0))
        path.addLine(to: CGPoint(x: qrsComplex, y: graphView.halfHeight + 40.0))
        path.addLine(to: CGPoint(x: qrsComplexEndPoint, y: graphView.halfHeight))
        
        let gapBetweenQRSAndTWave: CGFloat = 20.0
        let tWaveStartPoint = qrsComplexEndPoint + gapBetweenQRSAndTWave
        path.addLine(to: CGPoint(x: tWaveStartPoint, y: graphView.halfHeight))
        
        // T Point Curve
        let tWaveEndX = tWaveStartPoint + tWaveWidth
        print(tWaveEndX)
        path.addQuadCurve(to: CGPoint(x: tWaveEndX, y: graphView.halfHeight), controlPoint: CGPoint(x: tWaveEndX - 7.0, y: graphView.halfHeight - 30.0))
        
        movingPoint = tWaveEndX
        startInterval = tWaveEndX + gapBetweenTwoIntervals
        path.addLine(to: CGPoint(x: startInterval, y: graphView.halfHeight))
        bezierPath.append(path)
    }
    
    shapeLayer.path = bezierPath.cgPath
    
    animation.fromValue = 0.0
    animation.duration = 205 * 2
    shapeLayer.add(animation, forKey: "PathAnimation")
    
    return bezierPath
}

}

【问题讨论】:

  • 你能添加一些代码让别人知道你到目前为止做了什么吗?
  • 当然...........
  • 我看到了您的代码,我觉得它看起来不错。您能否具体说明您面临的问题?
  • @PrateekVarshney 嗨,实际上我正在使用循环作为贝塞尔路径。但是我想在从服务器更改值时在运行时附加贝塞尔路径。
  • 所以我的理解是,目前您正在使用循环来创建它,但您想根据服务器响应在没有循环的情况下获得相同的效果?

标签: ios swift bezier cashapelayer cabasicanimation


【解决方案1】:

我设法解决了您的问题,请检查并告诉我它是否适合您。

注意 - 我添加了一个按钮单击以添加更多图形模式,而不是服务器响应。您可以通过从服务器响应成功方法调用按钮点击代码来使用服务器响应来执行相同的操作。

import UIKit

class GraphViewController: UIViewController {

@IBOutlet weak var graphView: UIView!

// MARK:- PROPERTIES
var movingPoint: CGFloat = 0.0
var startInterval: CGFloat = 10.0
var noOfIntervals: CGFloat = 0
var intervalWidth: CGFloat = 0
var pWaveWidth: CGFloat = 20.0
var qrsWaveWidth: CGFloat = 15
var tWaveWidth: CGFloat = 30
var gapBetweenTwoIntervals: CGFloat = 50
let animation = CABasicAnimation(keyPath: "strokeEnd")

override func viewDidLoad() {
    super.viewDidLoad()
    
    graphView.translatesAutoresizingMaskIntoConstraints = true
    graphView.backgroundColor = .blue
    graphView.frame.size = CGSize(width: 100000, height: 250)
    DispatchQueue.main.async {
        self.graphView.layoutIfNeeded()
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    createBezierPath(repeatLoop: 1)
}

@objc func createBezierPath(repeatLoop: Int) {
    let pathsArray = UIBezierPath()
    
    let shapeLayer = CAShapeLayer()
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = UIColor.red.cgColor
    shapeLayer.lineWidth = 2.0
    
    for _ in 0..<repeatLoop {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: movingPoint, y: graphView.halfHeight))
        path.addLine(to: CGPoint(x: startInterval, y: graphView.halfHeight))
        
        // P Point Curve
        let pWaveX = startInterval + pWaveWidth
        path.addQuadCurve(to: CGPoint(x: pWaveX, y: graphView.halfHeight), controlPoint: CGPoint(x: pWaveX - 6.0, y: graphView.halfHeight - 30.0))
        
        let gapBetweenPAndQRS: CGFloat = 20.0
        path.addLine(to: CGPoint(x: (pWaveX + gapBetweenPAndQRS), y: graphView.halfHeight))
        
        // QRS
        let qrsStartPoint = pWaveX + gapBetweenPAndQRS
        let qrsComplex = qrsStartPoint + qrsWaveWidth
        let qrsComplexEndPoint = qrsComplex + (qrsWaveWidth / 2)
        path.addLine(to: CGPoint(x: qrsStartPoint + (qrsWaveWidth / 2), y: graphView.halfHeight - 70.0))
        path.addLine(to: CGPoint(x: qrsComplex, y: graphView.halfHeight + 40.0))
        path.addLine(to: CGPoint(x: qrsComplexEndPoint, y: graphView.halfHeight))
        
        let gapBetweenQRSAndTWave: CGFloat = 20.0
        let tWaveStartPoint = qrsComplexEndPoint + gapBetweenQRSAndTWave
        path.addLine(to: CGPoint(x: tWaveStartPoint, y: graphView.halfHeight))
        
        // T Point Curve
        let tWaveEndX = tWaveStartPoint + tWaveWidth
        print(tWaveEndX)
        path.addQuadCurve(to: CGPoint(x: tWaveEndX, y: graphView.halfHeight), controlPoint: CGPoint(x: tWaveEndX - 7.0, y: graphView.halfHeight - 30.0))
        
        movingPoint = tWaveEndX
        startInterval = tWaveEndX + gapBetweenTwoIntervals
        path.addLine(to: CGPoint(x: startInterval, y: graphView.halfHeight))
        pathsArray.append(path)
        
        shapeLayer.path = pathsArray.cgPath
        
        animation.fromValue = 0.0
        animation.duration = Double(repeatLoop) * 2
        shapeLayer.add(animation, forKey: "PathAnimation")
    }
    
    graphView.layer.addSublayer(shapeLayer)
}

@IBAction func btnTap(_ sender: Any) {
    createBezierPath(repeatLoop: 2)
}
}

extension UIView {
var halfHeight: CGFloat {
    return self.frame.size.height / 2.0
}
}

乐于助人:)

【讨论】:

    猜你喜欢
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2011-03-30
    相关资源
    最近更新 更多