Bezierpath绘制五角星(swift星级评分控件)

效果


评分效果

五角星各点的数学坐标出处

根据该数学坐标转换成UIView内坐标,生成正五角星

//Hello, this is Jack!
//  JKsStar.swift

import UIKit

class JKsStar: UIView {
    private var fillView: UIView!
    private let layerMask = CAShapeLayer()
    private let border = CAShapeLayer()
    
    
    var percent: CGFloat = 0 {  //0~1
        didSet {
            var frame = fillView.frame
            let width = self.bounds.size.width*percent
            frame.size.width = width
            fillView.frame = frame
        }
    }
    
    var fillColor: UIColor = UIColor.blue {
        didSet {
            fillView.backgroundColor = fillColor
        }
    }
    
    var borderColor = UIColor.blue {
        didSet {
            border.strokeColor = borderColor.cgColor
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        var fframe = self.bounds //!!!!!!! 不是frame
        let fWidth = self.bounds.size.width*percent
        fframe.size.width = fWidth
        
        fillView = UIView(frame: fframe)
        
        fillView.backgroundColor = fillColor
        self.addSubview(fillView)
        
        //在数学坐标轴的坐标
        let r: Double = Double(frame.size.width/2.0)
        
        let a_x: Double = 0
        let a_y = r
        let b_x = cos_degree(18)*r
        let b_y = sin_degree(18)*r
        let c_x = cos_degree(54)*r
        let c_y = -sin_degree(54)*r
        let d_x = -cos_degree(54)*r
        let d_y = -sin_degree(54)*r
        let e_x = -cos_degree(18)*r
        let e_y = sin_degree(18)*r
        
        //        let a = CGPoint(x: a_x, y: a_y)
        //        let b = CGPoint(x: b_x, y: b_y)
        //        let c = CGPoint(x: c_x, y: c_y)
        //        let d = CGPoint(x: d_x, y: d_y)
        //        let e = CGPoint(x: e_x, y: e_y)
        
        let tan_18_2 = tan(18/180*Double.pi)*tan(18/180*Double.pi)
        let t = (1 + tan_18_2)/(3-tan_18_2) //= 0.3819660112501
        let r_t = r*t
        
        let aa_x: Double = 0
        let aa_y = -r_t
        let bb_x = -r_t*cos_degree(18)
        let bb_y = -r_t*sin_degree(18)
        let cc_x = -r_t*cos_degree(54)
        let cc_y = r_t*sin_degree(54)
        let dd_x = r_t*cos_degree(54)
        let dd_y = r_t*sin_degree(54)
        let ee_x = r_t*cos_degree(18)
        let ee_y = -r_t*sin_degree(18)
        
        //        let aa = CGPoint(x: aa_x, y: aa_y)
        //        let bb = CGPoint(x: bb_x, y: bb_y)
        //        let cc = CGPoint(x: cc_x, y: cc_y)
        //        let dd = CGPoint(x: dd_x, y: dd_y)
        //        let ee = CGPoint(x: ee_x, y: ee_y)
        //转换为正方形view(与圆内切)内部坐标
        let a_v = CGPoint(x: r + a_x, y: r - a_y)
        let b_v = CGPoint(x: r + b_x, y: r - b_y)
        let c_v = CGPoint(x: r + c_x, y: r - c_y)
        let d_v = CGPoint(x: r + d_x, y: r - d_y)
        let e_v = CGPoint(x: r + e_x, y: r - e_y)
        
        let aa_v = CGPoint(x: r + aa_x, y: r - aa_y)
        let bb_v = CGPoint(x: r + bb_x, y: r - bb_y)
        let cc_v = CGPoint(x: r + cc_x, y: r - cc_y)
        let dd_v = CGPoint(x: r + dd_x, y: r - dd_y)
        let ee_v = CGPoint(x: r + ee_x, y: r - ee_y)
        
        let starPath_bz = UIBezierPath()
        starPath_bz.move(to: a_v)
        starPath_bz.addLine(to: dd_v)
        starPath_bz.addLine(to: b_v)
        starPath_bz.addLine(to: ee_v)
        starPath_bz.addLine(to: c_v)
        starPath_bz.addLine(to: aa_v)
        starPath_bz.addLine(to: d_v)
        starPath_bz.addLine(to: bb_v)
        starPath_bz.addLine(to: e_v)
        starPath_bz.addLine(to: cc_v)
        starPath_bz.close()
        
        layerMask.backgroundColor = UIColor.red.cgColor
        layerMask.path = starPath_bz.cgPath
        
        self.layer.mask = layerMask
        //border
        border.path = starPath_bz.cgPath
        border.strokeColor = borderColor.cgColor
        border.fillColor = nil
        self.layer.addSublayer(border)
        
    }
    
    func sin_degree(_ degree: Double) -> Double {
        return sin(degree/180*Double.pi)
    }
    
    func cos_degree(_ degree: Double) -> Double {
        return cos(degree/180*Double.pi)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

用法

override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }
    //    初始化UI
    func setupUI() {
        if starArray.count > 0 {
            starArray.removeAll()
        }
        for i in 0..<5 {
            let star = createStarAt(index: i)
            starArray.append(star)
            stars_view.addSubview(star)
        }
    }

func createStarAt(index: Int) -> JKsStar {
        let starD: CGFloat = 23.0
        let starSpacing: CGFloat = 6.0
        let starX = (starD + starSpacing)*CGFloat(index)
        
        let star = JKsStar(frame: CGRect(x: starX, y: 0, width: starD, height: starD))
        star.backgroundColor = UIColor.white
        star.borderColor = ThemeColor_Blue
        star.fillColor = ThemeColor_Blue
        return star
    }
    
    func starAt(index: Int) -> JKsStar {
        return starArray[index]
    }
    
    //评分(0~5分)
    func setScore(_ value: CGFloat) {
        for i in 0..<5 {    //5个星星
            let star = starAt(index: i)
            star.percent = 1
            
            let index = CGFloat(i)
            if index < floor(value) {
                star.percent = 1
            }else if index <= value {
                star.percent = value - index
            }else {
                star.percent = 0
            }
        }
    }

附注:
/*
假设五角星外接圆半径为1,有一个角朝上,以五角星中心为原点:
则五个角顶点坐标分别为(按顺时针):
A(0,1)
B(cos18°,sin18°)
C(cos54°,-sin54°)
D(-cos54°,-sin54°)
E(-cos18°,sin18°)
假设t为内部五边形外接圆半径,
t=(1+tan^2 (18°))/(3-tan^2 (18°)),即0.3819660112501
则五个顶点所对应的坐标为(即内部五边形的五个顶点):
AA(0,-t)
BB(-tcos18°,-tsin18°)
CC(-tcos54°,tsin54°)
DD(tcos54°,tsin54°)
EE(tcos18°,-tsin18°)
*/

数学坐标系
iOS UIView坐标
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 1、生成快捷方式 sudo gedit /usr/share/applications/Studio.deskto...
    拉肚阅读 316评论 0 0
  • 感赏今天进入到一个温暖正能量的大家庭。感谢自己给自己一个机会。偶然听到了锦明老师的亲子教育音频,说到了容易落地...
    泉水清阅读 136评论 1 2
  • 有时,内心被触动 仅仅因为偶然的一句话 抑或,一次真诚的帮助 而这暖,如同向日葵绽放。
    小绵羊的兔先生阅读 136评论 0 0
  • 在教父眼中友谊 ,是通行的货币 ;忠诚 ,是最好的礼物 ;缄默 ,是唯一的规则 。他藐视一切价值 ,不给警告 ,不...
    子虚乌有先生阅读 224评论 0 0