Ios .circleAngle)-min(circleAngle,self.circleAngle))/2.0+min(circleAngle,self.circleAngle) 让动画=CAKeyframeAnimation(关键路径:“transform.r
.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) } }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
因此,您希望圆围绕其中心旋转,但希望圆从其当前方向开始旋转,并开始以用户移动手指的任何方式旋转?发布你当前的轮换代码,以及你的设置代码。是的,这正是我想要实现的。当前代码可在此处下载:@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)
}
}