美文网首页
Bezierpath绘制五角星(swift星级评分控件)

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

作者: 姬歌 | 来源:发表于2018-08-03 19:28 被阅读35次

    效果


    评分效果

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

    根据该数学坐标转换成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坐标

    相关文章

      网友评论

          本文标题:Bezierpath绘制五角星(swift星级评分控件)

          本文链接:https://www.haomeiwen.com/subject/ssfuvftx.html