Ios .circleAngle)-min(circleAngle,self.circleAngle))/2.0+min(circleAngle,self.circleAngle) 让动画=CAKeyframeAnimation(关键路径:“transform.r

Ios .circleAngle)-min(circleAngle,self.circleAngle))/2.0+min(circleAngle,self.circleAngle) 让动画=CAKeyframeAnimation(关键路径:“transform.r,ios,swift,animation,rotation,caanimation,Ios,Swift,Animation,Rotation,Caanimation,.circleAngle)-min(circleAngle,self.circleAngle))/2.0+min(circleAngle,self.circleAngle) 让动画=CAKeyframeAnimation(关键路径:“transform.rotation.z”) 动画。持续时间=0.25 animation.values=[self.circleAngle,midAngle,circleAngle] animation.keyTimes=[0.0,0.5,1.0] animati

.circleAngle)-min(circleAngle,self.circleAngle))/2.0+min(circleAngle,self.circleAngle) 让动画=CAKeyframeAnimation(关键路径:“transform.rotation.z”) 动画。持续时间=0.25 animation.values=[self.circleAngle,midAngle,circleAngle] animation.keyTimes=[0.0,0.5,1.0] animation.timingFunction=CAMediaTimingFunction(名称:kCAMediaTimingFunctionEaseInEaseOut) circleLayer.addAnimation(动画,forKey:“抖动”) } CATransaction.commit() self.backingPointerAngle=圆形 } /**绘制线段图层路径**/ func update(){ 设中心=CGPoint(x:circleLayer.bounds.size.width/2.0,y:circleLayer.bounds.size.height/2.0) 让半径:CGFloat=min(circleLayer.bounds.size.width,circleLayer.bounds.size.height)/2*1 设seg1Path=UIBezierPath(弧中心:中心,半径:半径,星形缠结:0.0,端角:分段大小,顺时针:true) seg1Path.addLineToPoint(中间) seg1Layer.path=seg1Path.CGPath 设seg2Path=UIBezierPath(弧中心:中心,半径:半径,星形缠结:分段大小,端角:分段大小*2,顺时针:true) seg2Path.addLineToPoint(中间) seg2Layer.path=seg2Path.CGPath 设seg3Path=UIBezierPath(弧心:中心,半径:半径,星形缠结:分段大小*2,端角:分段大小*3,顺时针:true) seg3Path.addLineToPoint(中间) seg3Layer.path=seg3Path.CGPath 设seg4Path=UIBezierPath(弧心:中心,半径:半径,星形缠结:分段大小*3,端角:分段大小*4,顺时针:true) seg4Path.addLineToPoint(中间) seg4Layer.path=seg4Path.CGPath } /**更新层的框架和位置**/ func更新(边界:CGRect){ 设位置=CGPoint(x:bounds.width/2.0,y:bounds.height/2.0) circleLayer.position=位置 circleLayer.bounds=边界 circleLayer.addSublayer(seg1Layer) circleLayer.addSublayer(seg2Layer) circleLayer.addSublayer(seg3Layer) circleLayer.addSublayer(seg4Layer) 更新() } } 导入UIKit.UIgestureRecognitizerSubclass 私有类TapGestureRecognizer:UITapGestureRecognizer{ 变量旋转:CGFloat=0.0 覆盖func touchesBegined(触摸:设置,withEvent事件:UIEvent){ super.touchsbegind(touchs,withEvent:event) 如果让触摸=触摸[触摸.开始索引]为?UITouch{ self.rotation=位置的旋转(touch.locationInView(self.view)) } } func rotationForLocation(位置:CGPoint)->CGFloat{ 让offset=CGPoint(x:location.x-view!.bounds.midX,y:location.y-view!.bounds.midY) 返回atan2(偏移量y、偏移量x) } } 协议RotateStartDelegate{ 函数旋转开始(起始点:CGPoint,角度:CGFloat) } 私有类RotationGestureRecognizer:UIPanGestureRecognizer{ /**旋转角**/ 变量旋转:CGFloat=0.0 变量旋转开始:CGFloat=0.0 var currentState:String=“空闲” 变量rotationDelegate:RotateStartDelegate init(委托:RotateStartDelegate,目标:AnyObject,操作:选择器){ self.rotationDelegate=委托 super.init(目标:目标,操作:操作) } 覆盖func touchesBegined(触摸:设置,withEvent事件:UIEvent){ super.touchsbegind(touchs,withEvent:event) self.currentState=“开始” 如果让触摸=触摸[触摸.开始索引]为?UITouch{ self.rotationDelegate.rotationStart(touch.locationInView(self.view),角度:rotationForLocation(touch.locationInView(self.view))) } } 覆盖功能触摸移动(触摸:设置,withEvent事件:UIEvent){ super.touchsmoved(touchs,with event:event) self.currentState=“拖动” UpdateRotationWithTouchs(触摸) } 覆盖函数touchesend(touch:Set!,withEvent:UIEvent!){ super.touchesend(touchs,withEvent:event) self.currentState=“空闲” } func UpdateRotationWithTouchs(Touchs:Set){ 如果让触摸=触摸[触摸.开始索引]为?UITouch{ self.rotation=位置的旋转(touch.locationInView(self.view)) } } func rotationForLocation(位置:CGPoint)->CGFloat{ 让offset=CGPoint(x:location.x-view!.bounds.midX,y:location.y-view!.bounds.midY) 返回atan2(偏移量y、偏移量x) } }
因此,您希望圆围绕其中心旋转,但希望圆从其当前方向开始旋转,并开始以用户移动手指的任何方式旋转?发布你当前的轮换代码,以及你的设置代码。是的,这正是我想要实现的。当前代码可在此处下载:@duncac Questions也用当前轮换代码更新
import UIKit

func degreesToRadians (value:Double) -> Double {
    return value * M_PI / 180.0
}

func radiansToDegrees (value:Double) -> Double {
    return value * 180.0 / M_PI
}

func square (value:CGFloat) -> CGFloat {
    return value * value
}

@IBDesignable public class CircleControl: UIControl, RotateStartDelegate {
    private var backingValue: CGFloat = 0.0

    /** Layer renderer **/
    private let circleRenderer = CircleRenderer()

    /** Contains the receiver’s current value. */
    public var value: CGFloat {
        get { return backingValue }
        set { setValue(newValue, animated: false) }
    }

    public var angle: Double = 0.0

    /** Set the angle of the circle */
    public func setValue(value: CGFloat, animated: Bool) {
        if(value != self.value) {
            self.backingValue = value

            // Update human-readable angle
            var a = radiansToDegrees(Double(value))
            self.angle = (a >= 0) ? a : a + 360.0

            // Set angle
            circleRenderer.setCircleAngle(value, animated: animated)
            sendActionsForControlEvents(.ValueChanged)
        }
    }

    /** Contains a Boolean value indicating whether changes in the sliders value generate continuous update events. */
    public var continuous = true

    public override init(frame: CGRect) {
        super.init(frame: frame)

        createSubLayers()

        let gr = RotationGestureRecognizer(delegate: self, target: self, action: "handleRotation:")
        self.addGestureRecognizer(gr)

        let tr = TapGestureRecognizer(target: self, action: "handleTap:")
        self.addGestureRecognizer(tr)

        self.setValue(circleRenderer.segmentMiddle, animated: false)
    }

    public required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    /** Set bounds of all the sub layers **/
    func createSubLayers() {
        circleRenderer.update(bounds)

        layer.addSublayer(circleRenderer.circleLayer)
    }

    func rotationStart(startingPoint: CGPoint, angle: CGFloat) {
        println("Rotation started")
        println(startingPoint)

//        circleRenderer.setDragStartingAngle(angle)
//        
////        circleRenderer.circleLayer.anchorPoint = startingPoint
////
////        circleRenderer.backingPointerAngle = angle
////        circleRenderer.setCircleAngle(angle, animated: true)
    }

    /** Animate to the color usert tapped on **/
    func handleTap(sender: AnyObject) {
        let tr = sender as! TapGestureRecognizer

    }

    /** Update the angle **/
    func handleRotation(sender: AnyObject) {
        let gr = sender as! RotationGestureRecognizer

        self.value = gr.rotation

        // When the gesture has stopped make a small correction to the middle of the segment
        if (gr.state == UIGestureRecognizerState.Ended) || (gr.state == UIGestureRecognizerState.Cancelled) {
            var segmentSize:Double = 360 / 4
            if self.angle >= 0.0 && self.angle < segmentSize {
                self.setValue(circleRenderer.segmentMiddle, animated: true)
            } else if self.angle >= segmentSize && self.angle < segmentSize * 2 {
                self.setValue(circleRenderer.segmentMiddle * 3, animated: true)
            } else if self.angle >= segmentSize * 2 && self.angle < segmentSize * 3 {
                self.setValue(circleRenderer.segmentMiddle * -3, animated: true)
            } else if self.angle >= segmentSize * 3 && self.angle < segmentSize * 4 {
                self.setValue(circleRenderer.segmentMiddle * -1, animated: true)
            }
        }
    }
}

private class CircleRenderer {
    /** Angle properties **/
    var backingPointerAngle: CGFloat = 0.0
    var circleAngle: CGFloat {
        get { return backingPointerAngle }
        set { setCircleAngle(newValue, animated: false) }
    }

    /** Layers **/
    let circleLayer = CALayer()
    let seg1Layer = CAShapeLayer()
    let seg2Layer = CAShapeLayer()
    let seg3Layer = CAShapeLayer()
    let seg4Layer = CAShapeLayer()

    /** Segment size **/
    let segmentSize:CGFloat = CGFloat( ( M_PI*2 ) / 4)

    /** Middle of a segment. The angle to rotate to **/
    let segmentMiddle:CGFloat = CGFloat(( M_PI*2 ) / 8)

    /** Initialize the colors **/
    init() {
        seg1Layer.fillColor = UIColor.greenColor().CGColor!
        seg2Layer.fillColor = UIColor(red: 204, green: 0, blue: 0, alpha: 100).CGColor!
        seg3Layer.fillColor = UIColor(red: 255, green: 203, blue: 0, alpha: 100).CGColor!
        seg4Layer.fillColor = UIColor.blueColor().CGColor!

        circleLayer.opaque = true
        circleLayer.backgroundColor = UIColor.clearColor().CGColor!
    }

    func setDragStartingAngle(angle: CGFloat) {
        // Set orientation?
    }

    /** Change the angle of the circle, animated or not animated **/
    func setCircleAngle(circleAngle: CGFloat, animated: Bool) {
        CATransaction.begin()
        CATransaction.setDisableActions(true)

        circleLayer.transform = CATransform3DMakeRotation(circleAngle, 0.0, 0.0, 0.1)

        if animated {
            let midAngle = (max(circleAngle, self.circleAngle) - min(circleAngle, self.circleAngle) ) / 2.0 + min(circleAngle, self.circleAngle)

            let animation = CAKeyframeAnimation(keyPath: "transform.rotation.z")
            animation.duration = 0.25
            animation.values = [self.circleAngle, midAngle, circleAngle]
            animation.keyTimes = [0.0, 0.5, 1.0]

            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            circleLayer.addAnimation(animation, forKey: "shake")
        }

        CATransaction.commit()

        self.backingPointerAngle = circleAngle
    }

    /** Draw the segment layers paths **/
    func update() {
        let center = CGPoint(x: circleLayer.bounds.size.width / 2.0, y: circleLayer.bounds.size.height / 2.0)
        let radius:CGFloat = min(circleLayer.bounds.size.width, circleLayer.bounds.size.height) / 2 * 1

        let seg1Path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0.0, endAngle: segmentSize, clockwise: true)
        seg1Path.addLineToPoint(center)
        seg1Layer.path = seg1Path.CGPath

        let seg2Path = UIBezierPath(arcCenter: center, radius: radius, startAngle: segmentSize, endAngle: segmentSize*2, clockwise: true)
        seg2Path.addLineToPoint(center)
        seg2Layer.path = seg2Path.CGPath

        let seg3Path = UIBezierPath(arcCenter: center, radius: radius, startAngle: segmentSize*2, endAngle: segmentSize*3, clockwise: true)
        seg3Path.addLineToPoint(center)
        seg3Layer.path = seg3Path.CGPath

        let seg4Path = UIBezierPath(arcCenter: center, radius: radius, startAngle: segmentSize*3, endAngle: segmentSize*4, clockwise: true)
        seg4Path.addLineToPoint(center)
        seg4Layer.path = seg4Path.CGPath
    }

    /** Update the frame and position of the layers **/
    func update(bounds: CGRect) {
        let position = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0)

        circleLayer.position = position
        circleLayer.bounds = bounds

        circleLayer.addSublayer(seg1Layer)
        circleLayer.addSublayer(seg2Layer)
        circleLayer.addSublayer(seg3Layer)
        circleLayer.addSublayer(seg4Layer)

        update()
    }
}

import UIKit.UIGestureRecognizerSubclass

private class TapGestureRecognizer : UITapGestureRecognizer {
    var rotation: CGFloat = 0.0
    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        super.touchesBegan(touches, withEvent: event)

        if let touch = touches[touches.startIndex] as? UITouch {
            self.rotation = rotationForLocation(touch.locationInView(self.view))
        }
    }

    func rotationForLocation(location: CGPoint) -> CGFloat {
        let offset = CGPoint(x: location.x - view!.bounds.midX, y: location.y - view!.bounds.midY)
        return atan2(offset.y, offset.x)
    }
}

protocol RotateStartDelegate {
    func rotationStart(startingPoint: CGPoint, angle: CGFloat)
}

private class RotationGestureRecognizer: UIPanGestureRecognizer {
    /** Angle of rotation **/
    var rotation: CGFloat = 0.0
    var rotationStart: CGFloat = 0.0
    var currentState: String = "idle"

    var rotationDelegate: RotateStartDelegate

    init(delegate: RotateStartDelegate, target: AnyObject, action: Selector) {
        self.rotationDelegate = delegate

        super.init(target: target, action: action)
    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        super.touchesBegan(touches, withEvent: event)

        self.currentState = "begin"

        if let touch = touches[touches.startIndex] as? UITouch {
            self.rotationDelegate.rotationStart(touch.locationInView(self.view), angle: rotationForLocation(touch.locationInView(self.view)))
        }
    }

    override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
        super.touchesMoved(touches, withEvent: event)

        self.currentState = "dragging"
        updateRotationWithTouches(touches)
    }

    override func touchesEnded(touches: Set<NSObject>!, withEvent event: UIEvent!) {
        super.touchesEnded(touches, withEvent: event)

        self.currentState = "idle"
    }

    func updateRotationWithTouches(touches: Set<NSObject>) {
        if let touch = touches[touches.startIndex] as? UITouch {
            self.rotation = rotationForLocation(touch.locationInView(self.view))
        }
    }

    func rotationForLocation(location: CGPoint) -> CGFloat {
        let offset = CGPoint(x: location.x - view!.bounds.midX, y: location.y - view!.bounds.midY)
        return atan2(offset.y, offset.x)
    }
}