如何在iOS / Swift中限制多个弧层时刻?

时间:2016-07-31 06:53:33

标签: ios swift uibezierpath uipangesturerecognizer cashapelayer

我需要使用Swift开发以下UI屏幕ios。

enter image description here 要求屏幕

在上面的两个圆圈中,每个分段的移动都可以推或拉到其他圆圈。 enter image description here

我写了下面的代码来实现它

    import UIKit

    class ArcView: UIView {

        let lineWidth: CGFloat = 40
        var path: UIBezierPath!
        var startAngle:CGFloat?
        var endAngle:CGFloat?
        var radius:CGFloat?
        var strokeColor:UIColor?
        var arcCenter:CGPoint?
        var tapPoint:CGPoint?
        var destPoint:CGPoint?
        var initialCenter:CGPoint?

        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        func setProps(startAngle:CGFloat,endAngle:CGFloat,center:CGPoint, radius:CGFloat,color:UIColor) {
            self.radius=radius
            self.startAngle=startAngle
            self.endAngle=endAngle
            self.strokeColor=color
            self.arcCenter=center
            self.backgroundColor = UIColor.clearColor()
            initGestureRecognizers()
            self.initialCenter=self.center
        }

        func initGestureRecognizers() {
            let panGR = UIPanGestureRecognizer(target: self, action: "didPan:")
            addGestureRecognizer(panGR)
        }

        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let touch = touches.first
            tapPoint = touch!.locationInView(self)
        }

        override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let touch = touches.reverse().first
            destPoint = touch!.locationInView(self)
        }

        override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let touch = touches.reverse().first
            destPoint = touch!.locationInView(self)
        }


        func didPan(panGR: UIPanGestureRecognizer) {
            self.superview!.bringSubviewToFront(self)

            var translation = panGR.translationInView(self)

            translation = CGPointApplyAffineTransform(translation, self.transform)

            updateLocation(translation)
            panGR.setTranslation(CGPointZero, inView: self)

    //        self.superview!.sendSubviewToBack(self)
        }

        func isMoveAllowed() -> Bool {
            if(arcCenter?.distanceFrom(tapPoint!)<=((arcCenter?.distanceFrom(destPoint!))!+(destPoint?.distanceFrom(tapPoint!))!)) {
                return true
            }
            return false
        }

        func updateLocation(location:CGPoint) {
            if isMoveAllowed() {
                self.center.x += location.x
                self.center.y += location.y
            }
        }

        override func drawRect(rect: CGRect) {
            self.path = UIBezierPath(arcCenter: arcCenter!, radius: radius!, startAngle: startAngle!, endAngle:endAngle!, clockwise: true)
            let circleLayer :CAShapeLayer = CAShapeLayer()
            circleLayer.path = self.path.CGPath
            circleLayer.lineWidth = 40
            circleLayer.strokeColor = strokeColor!.CGColor
            circleLayer.fillColor = UIColor.clearColor().CGColor
            self.layer.addSublayer(circleLayer)
            self.path.fill()
            self.path.stroke()
        }
    }

    extension CGPoint {
        func distanceFrom(p:CGPoint) -> CGFloat {
            return sqrt(pow((p.x - self.x),2) + pow((p.y - self.y),2))
        }
    }

View Controller代码是

    import UIKit

    class ViewController: UIViewController {

        override func viewDidLoad() {
            super.viewDidLoad()

        let center:CGPoint = CGPoint(x: 215,y: 325)
            let innerRadius:CGFloat = CGFloat(55)
            let outerRadius:CGFloat = CGFloat(98)

            let innerCirclePath = UIBezierPath(arcCenter: center, radius: innerRadius, startAngle: CGFloat(M_PI * 1.5), endAngle:CGFloat(M_PI * 3.5), clockwise: true)

            let outerCirclePath = UIBezierPath(arcCenter: center, radius: outerRadius, startAngle: CGFloat(M_PI * 1.5), endAngle:CGFloat(M_PI * 3.5), clockwise: true)

            addBlankColorLayer(0,endHour: totalHours,eachMinute:eachMinute,innerCirclePath: innerCirclePath,blankColor: UIColor.grayColor())

            addBlankColorLayer(0,endHour: totalHours,eachMinute:eachMinute,innerCirclePath: outerCirclePath,blankColor: UIColor.grayColor())

            var eventTimes:[(CGFloat,CGFloat)] = [(0,1),(1.5,2),(2.5,3.0)]

            for times in eventTimes {
            let arc:ArcView=ArcView(frame:self.view.frame)
                arc.setProps(times.0,endAngle:times.1,center:center, radius:outerRadius,color:UIColor.redColor())
                self.view.addSubview(arc)
            }
            // Do any additional setup after loading the view, typically from a nib.
        }
        func addBlankColorLayer(startHour:CGFloat,endHour:CGFloat,eachMinute:CGFloat,innerCirclePath:UIBezierPath,blankColor:UIColor) {
            let circleLayer :CAShapeLayer = CAShapeLayer()
            circleLayer.path = innerCirclePath.CGPath
            circleLayer.strokeStart = eachMinute*startHour*60;
            circleLayer.strokeEnd = eachMinute * 60 * (endHour)
            circleLayer.lineWidth = 40
            circleLayer.strokeColor = blankColor.CGColor
            circleLayer.fillColor = UIColor.clearColor().CGColor
            view.layer.addSublayer(circleLayer)

        }
    }

我能够实现这个目标

Result image

在这个我能够实现泛手势的时刻也如下 Allowed

但现在我遇到了很多问题。

  • 无法单独选择每个图层/细分/视图。我应该遵循什么方法来实现它?
  • 如何将每个图层/细分/视图时刻仅限于中心?以下是错误的时刻图片

Not allowed

感谢任何帮助。

0 个答案:

没有答案