-
-
Save taktamur/0ee02697c9f380bd90f6af831b187778 to your computer and use it in GitHub Desktop.
円グラフアニメーションちっくな何かの試作品。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // CircleView.swift | |
| // CircleViewSample | |
| // | |
| // Created by 田村孝文 on 2016/08/07. | |
| // Copyright © 2016年 田村孝文. All rights reserved. | |
| // | |
| import Foundation | |
| import UIKit | |
| @IBDesignable | |
| class CircleView:UIView{ | |
| @IBInspectable var rate:Double = 0 | |
| { | |
| didSet{ | |
| NSLog( "didSet.rate=\(rate)") | |
| if rate<0 { | |
| rate = 0 | |
| }else if rate > 1.0 { | |
| rate = 1.0 | |
| } | |
| } | |
| } | |
| @IBInspectable var lineWidth:CGFloat = 10 // 線の幅 | |
| @IBInspectable var fontSize:CGFloat = 12 | |
| @IBInspectable var zeroColor:UIColor = UIColor.blueColor() | |
| @IBInspectable var perfectColor:UIColor = UIColor.redColor() | |
| override func drawRect(rect: CGRect) { | |
| let boundsCenter = CGPoint(x: self.bounds.size.width/2, | |
| y: self.bounds.size.height/2) | |
| let startAngle = CGFloat(-1 * M_PI_2) | |
| let endAngle = startAngle + CGFloat(M_PI*2 * self.rate) | |
| let radius = min(boundsCenter.x,boundsCenter.y) - lineWidth/2 | |
| let circle = UIBezierPath(arcCenter:boundsCenter, | |
| radius: radius, | |
| startAngle: startAngle, | |
| endAngle: endAngle, | |
| clockwise: true) | |
| circle.lineWidth = self.lineWidth; | |
| let color = UIColor.mixColor(self.zeroColor, | |
| to: self.perfectColor, | |
| rate: self.rate) | |
| color.setStroke() | |
| circle.stroke() | |
| let attrs = self.stringAttribute() | |
| let rect = self.rectWithString("100%" , attrs: attrs) | |
| "\(Int(rate*100))%".drawInRect(rect, withAttributes:attrs) | |
| } | |
| func stringAttribute()->[String : AnyObject]{ | |
| let font = UIFont.systemFontOfSize(fontSize) | |
| let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle | |
| style.alignment = NSTextAlignment.Right | |
| return [NSFontAttributeName:font, | |
| NSParagraphStyleAttributeName:style] | |
| } | |
| func rectWithString(str:String, attrs: [String : AnyObject])->CGRect{ | |
| let size = str.sizeWithAttributes(attrs) | |
| let origin = CGPoint(x: self.bounds.size.width/2 - size.width/2, | |
| y: self.bounds.size.height/2 - size.height/2) | |
| return CGRect(origin: origin, size: size) | |
| } | |
| } | |
| extension UIColor{ | |
| static func mixColor(from:UIColor, to:UIColor, rate:Double)->UIColor{ | |
| func rgbaArray(c:UIColor)->[CGFloat]{ | |
| var red: CGFloat = 1.0 | |
| var green: CGFloat = 1.0 | |
| var blue: CGFloat = 1.0 | |
| var alpha: CGFloat = 1.0 | |
| c.getRed(&red, green: &green, blue: &blue, alpha: &alpha) | |
| return [red,green,blue,alpha] | |
| } | |
| let a1:[CGFloat] = rgbaArray(from) | |
| let a2:[CGFloat] = rgbaArray(to) | |
| let rgba:[CGFloat] = (0...3) | |
| .map { (i:Int) -> CGFloat in | |
| return (a1[i] + (a2[i] - a1[i])*CGFloat(rate)) | |
| } | |
| return UIColor(red: rgba[0], | |
| green: rgba[1], | |
| blue: rgba[2], | |
| alpha: rgba[3]) | |
| } | |
| } | |
| class AnimationInfo:NSObject{ | |
| internal var startTime:NSTimeInterval | |
| internal var duration:NSTimeInterval | |
| init(duration:NSTimeInterval) { | |
| self.startTime = NSDate().timeIntervalSince1970 | |
| self.duration = duration | |
| } | |
| func progress()->Double{ | |
| let now = NSDate().timeIntervalSince1970 | |
| return (now - self.startTime)/self.duration; | |
| } | |
| } | |
| extension CircleView{ | |
| func startAnimationWithBlock(duration:NSTimeInterval){ | |
| func loop(info:AnimationInfo){ | |
| let progress = info.progress() | |
| self.rate = progress | |
| self.setNeedsDisplay() | |
| if( progress > 1.0 ){ | |
| return; | |
| } | |
| let queue = dispatch_get_main_queue() | |
| let time = dispatch_time(DISPATCH_TIME_NOW, 0) | |
| dispatch_after(time, queue) { () -> Void in | |
| loop(info) | |
| } | |
| } | |
| let info = AnimationInfo(duration: duration) | |
| loop(info) | |
| } | |
| } | |
| extension CircleView{ | |
| func startAnimation(duration:NSTimeInterval){ | |
| let animationInfo = AnimationInfo(duration: duration) | |
| let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, | |
| target: self, | |
| selector: Selector("update:"), | |
| userInfo:animationInfo, | |
| repeats:true) | |
| timer.fire() | |
| } | |
| func update(timer:NSTimer){ | |
| let animationInfo = timer.userInfo as? AnimationInfo | |
| if let animationInfo = animationInfo { | |
| let progress = animationInfo.progress() | |
| if( progress > 1.0 ){ | |
| timer.invalidate() | |
| } | |
| self.rate = progress | |
| self.setNeedsDisplay() | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment