zoukankan      html  css  js  c++  java
  • [控件] 画饼状图的控件

    画饼状图的控件

    效果

    注意:支持遮罩效果

    源码

    https://github.com/YouXianMing/UI-Component-Collection

    //
    //  CircleView.h
    //  YXMWeather
    //
    //  Created by XianMingYou on 15/5/12.
    //  Copyright (c) 2015年 XianMingYou. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface CircleView : UIView
    
    /**
     *  线条宽度
     */
    @property (nonatomic)         CGFloat   lineWidth;
    
    /**
     *  线条颜色
     */
    @property (nonatomic, strong) UIColor  *lineColor;
    
    /**
     *  旋转方向
     */
    @property (nonatomic)         BOOL      clockWise;
    
    /**
     *  开始角度
     */
    @property (nonatomic)         CGFloat   startAngle;
    
    /**
     *  初始化view
     */
    - (void)buildView;
    
    /**
     *  做strokeEnd动画
     *
     *  @param value    取值 [0, 1]
     *  @param animated 是否执行动画
     *  @param duration 动画持续的时间
     */
    - (void)strokeEnd:(CGFloat)value animated:(BOOL)animated duration:(CGFloat)duration;
    
    /**
     *  做strokeStart动画
     *
     *  @param value    取值 [0, 1]
     *  @param animated 是否执行动画
     *  @param duration 动画持续的时间
     */
    - (void)strokeStart:(CGFloat)value animated:(BOOL)animated duration:(CGFloat)duration;
    
    /**
     *  便利构造器创建出实例对象
     *
     *  @param frame     frame值
     *  @param width     线条宽度
     *  @param color     线条颜色
     *  @param clockWise 是否是顺时钟
     *  @param angle     开始是否的角度(取值范围 0° ~ 360°)
     *
     *  @return 实例对象
     */
    + (instancetype)circleViewWithFrame:(CGRect)frame
                              lineWidth:(CGFloat)width
                              lineColor:(UIColor *)color
                              clockWise:(BOOL)clockWise
                             startAngle:(CGFloat)angle;
    
    @end
    //
    //  CircleView.m
    //  YXMWeather
    //
    //  Created by XianMingYou on 15/5/12.
    //  Copyright (c) 2015年 XianMingYou. All rights reserved.
    //
    
    #import "CircleView.h"
    #import "YXEasing.h"
    
    // 将度数转换为弧度
    #define   RADIAN(degrees)  ((M_PI * (degrees))/ 180.f)
    
    // 将弧度转换为度数
    #define   DEGREES(radian)  ((radian) * 180.f / M_PI)
    
    @interface CircleView ()
    
    @property (nonatomic, strong) CAShapeLayer *circleLayer; // 圆形layer
    
    @end
    
    @implementation CircleView
    
    /**
     *  初始化frame值
     *
     *  @param frame 尺寸值
     *
     *  @return 实例对象
     */
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            // 创建出layer
            [self createCircleLayer];
        }
        
        return self;
    }
    
    /**
     *  创建出layer
     */
    - (void)createCircleLayer {
        self.circleLayer       = [CAShapeLayer layer];
        self.circleLayer.frame = self.bounds;
        [self.layer addSublayer:self.circleLayer];
    }
    
    /**
     *  初始化view
     */
    - (void)buildView {
        // 初始化信息
        CGFloat  lineWidth = (self.lineWidth <= 0 ? 1 : self.lineWidth);
        UIColor *lineColor = (self.lineColor == nil ? [UIColor blackColor] : self.lineColor);
        CGSize   size      = self.bounds.size;
        CGFloat  radius    = size.width / 2.f - lineWidth / 2.f; // 设置半径(刚好贴到frame上面去)
        
        // 旋转方向
        BOOL clockWise = self.clockWise;
        CGFloat startAngle = 0;
        CGFloat endAngle   = 0;
        if (clockWise == YES) {
            startAngle = -RADIAN(180 - self.startAngle);
            endAngle   = RADIAN(180 + self.startAngle);
        } else {
            startAngle = RADIAN(180 - self.startAngle);
            endAngle   = -RADIAN(180 + self.startAngle);
        }
        
        // 创建出贝塞尔曲线
        UIBezierPath *circlePath 
            = [UIBezierPath bezierPathWithArcCenter:CGPointMake(size.height / 2.f, size.width / 2.f)
                                             radius:radius
                                         startAngle:startAngle
                                           endAngle:endAngle
                                          clockwise:clockWise];
    
        // 获取path
        self.circleLayer.path = circlePath.CGPath;
        
        // 设置颜色
        self.circleLayer.strokeColor = lineColor.CGColor;
        self.circleLayer.fillColor   = [[UIColor clearColor] CGColor];
        self.circleLayer.lineWidth   = lineWidth;
        self.circleLayer.strokeEnd   = 0.f;
    }
    
    - (void)strokeEnd:(CGFloat)value animated:(BOOL)animated duration:(CGFloat)duration {
        
        // 过滤掉不合理的值
        if (value <= 0) {
            value = 0;
        } else if (value >= 1) {
            value = 1.f;
        }
        
        if (animated) {
            // 关键帧动画
            CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animation];
            keyAnimation.keyPath              = @"strokeEnd";
            keyAnimation.duration             = duration;
            keyAnimation.values               = 
                [YXEasing calculateFrameFromValue:self.circleLayer.strokeEnd
                                          toValue:value
                                             func:CubicEaseInOut
                                       frameCount:duration * 60];
            
            // 执行动画
            self.circleLayer.strokeEnd = value;
            [self.circleLayer addAnimation:keyAnimation forKey:nil];
        } else {
            // 关闭动画
            [CATransaction setDisableActions:YES];
            self.circleLayer.strokeEnd = value;
            [CATransaction setDisableActions:NO];
        }
    }
    
    - (void)strokeStart:(CGFloat)value animated:(BOOL)animated duration:(CGFloat)duration {
        // 过滤掉不合理的值
        if (value <= 0) {
            value = 0;
        } else if (value >= 1) {
            value = 1.f;
        }
        
        if (animated) {
            // 关键帧动画
            CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animation];
            keyAnimation.keyPath              = @"strokeStart";
            keyAnimation.duration             = duration;
            keyAnimation.values               = 
            [YXEasing calculateFrameFromValue:self.circleLayer.strokeStart
                                      toValue:value
                                         func:CubicEaseInOut
                                   frameCount:duration * 60];
            
            // 执行动画
            self.circleLayer.strokeStart = value;
            [self.circleLayer addAnimation:keyAnimation forKey:nil];
        } else {
            // 关闭动画
            [CATransaction setDisableActions:YES];
            self.circleLayer.strokeStart = value;
            [CATransaction setDisableActions:NO];
        }
    }
    
    
    
    + (instancetype)circleViewWithFrame:(CGRect)frame
                              lineWidth:(CGFloat)width
                              lineColor:(UIColor *)color
                              clockWise:(BOOL)clockWise
                             startAngle:(CGFloat)angle {
        
        CircleView *circleView = [[CircleView alloc] initWithFrame:frame];
        circleView.lineWidth   = width;
        circleView.lineColor   = color;
        circleView.clockWise   = clockWise;
        circleView.startAngle  = angle;
        
        return circleView;
    }
    
    @end

    细节

    以上是几个核心的参数

  • 相关阅读:
    异常处理
    注解配置的Spring MVC
    React router
    Redux管理你的React应用
    Spring.Net 初探
    有效的XML: DTD(文档类型定义)介绍(转)
    Python 目录操作(转)
    nginx做反向负载均衡,后端服务器获取真实客户端ip(转)
    以正确的方式开源 Python 项目(转)
    Linux访问Windows共享文件夹 (转)
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4498977.html
Copyright © 2011-2022 走看看