美文网首页iOS视图
iOS ~ 贝塞尔曲线:二阶曲线图📈,ShapeLayer

iOS ~ 贝塞尔曲线:二阶曲线图📈,ShapeLayer

作者: 阳光下的叶子呵 | 来源:发表于2022-04-17 14:02 被阅读0次
    原理:

    // 起始点
    - (void)moveToPoint:(CGPoint)point;
    // 二阶曲线(两个控制点)
    - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
    原理(这里的天气温度曲线):endPoint:下一个端点的x、y轴坐标, controlPoint1:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和上一个startPoint.y, controlPoint2:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和下一个endPoint.y,

    关键代码:

    if (k == 0) { // 第一个,特殊处理
        // 第一个点,起始点。
        [weather_MaxTempPath moveToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width/375*67/2, [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (nextTemp - minTemp)))];
                
        } else {
                
        GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel0 = self.dailyWeathers[k-1];
        CGFloat lastTemp = [dailyWeatherModel0.day_MaxTemp floatValue];
                
        // 原理(这里的天气温度曲线):endPoint:下一个端点的x、y轴坐标, controlPoint1:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和上一个startPoint.y, controlPoint2:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和下一个endPoint.y,
        [weather_MaxTempPath addCurveToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k) , [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (nextTemp - minTemp)))
                            controlPoint1:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k - 67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (lastTemp - minTemp)))
                            controlPoint2:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k - 67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * ((nextTemp - minTemp))))];
    }
    
    代码:
    @property (nonatomic, strong) UIView        *top_LineRangeView; // 折线图📈的范围父view(温度)
    @property (nonatomic, strong) UIView        *top_LineLayerRangeView; // 折线图📈的范围父view(折线图layer)
    @property (nonatomic, strong) CAShapeLayer  *top_lineFatherLayer; // // 折线图的父layer
    
    - (void)refreshTableFooterView {
        
        /** 未来15日的预报: */
        [self.top_LineRangeView removeFromSuperview];
        [self.top_LineLayerRangeView removeFromSuperview];
        [self.top_lineFatherLayer removeFromSuperlayer];
        
        // 为防止缺少数据,这里重新设置一下scrollview 的内容宽度:
        self.top_chartContentScrollView.contentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width/375*(67*self.dailyWeathers.count), self.top_chartContentScrollView.frame.size.height);
        
        /**!!! 创建温度的背景view,(15天的 天气预览)  !!!*/
        _top_LineRangeView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.top_chartContentScrollView.contentSize.width, [UIScreen mainScreen].bounds.size.width/375*120)];
        self.top_LineRangeView.backgroundColor = [UIColor clearColor];
        self.top_LineRangeView.userInteractionEnabled = NO;
        [self.top_chartContentView addSubview:self.top_LineRangeView];
        
        _top_LineLayerRangeView = [[UIView alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.width/375*25, self.top_chartContentScrollView.contentSize.width, [UIScreen mainScreen].bounds.size.width/375*(120 - 50))];
        self.top_LineLayerRangeView.backgroundColor = [UIColor clearColor];
        self.top_LineLayerRangeView.userInteractionEnabled = NO;
        [self.top_chartContentView addSubview:self.top_LineLayerRangeView];
        
        
        /** 1、创建曲线图的父layer:120 - 50 = 70 */
        _top_lineFatherLayer = [[CAShapeLayer alloc] init];
        _top_lineFatherLayer.strokeColor = [UIColor clearColor].CGColor;
        
        UIBezierPath *bezierPath = [UIBezierPath
                                        bezierPathWithRoundedRect:CGRectMake(0, 0, self.top_chartContentScrollView.contentSize.width, [UIScreen mainScreen].bounds.size.width/375*(120 - 50))
                                        byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
                                        cornerRadii:CGSizeMake([UIScreen mainScreen].bounds.size.width/375*0, [UIScreen mainScreen].bounds.size.width/375*0)];
    
        _top_lineFatherLayer.lineWidth = [UIScreen mainScreen].bounds.size.width/375*0.01;
        // 颜色
        _top_lineFatherLayer.strokeColor = [UIColor clearColor].CGColor;
        // 背景填充色
        _top_lineFatherLayer.fillColor = [UIColor clearColor].CGColor;
        _top_lineFatherLayer.path = [bezierPath CGPath];
        [self.top_LineLayerRangeView.layer addSublayer:self.top_lineFatherLayer];
        
        /// 先找到15天的 最大温度和最低温度:(获取曲线图📈的范围)
        CGFloat maxTemp = 0;
        CGFloat minTemp = 0;
        
        NSMutableArray *temp_array = [NSMutableArray arrayWithCapacity:0];
        
        for (GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel in self.dailyWeathers) {
            NSString *day_MaxTemp = [NSString stringWithFormat:@"%@", dailyWeatherModel.day_MaxTemp];
            NSString *day_MinTemp = [NSString stringWithFormat:@"%@", dailyWeatherModel.day_MinTemp];
            // 15天内的所有最高温、最低温 都放到数组,(之下的for循环,获取全部温度中的最高温、最低温)
            [temp_array addObject:day_MaxTemp];
            [temp_array addObject:day_MinTemp];
        }
        
        for (int i = 0; i < temp_array.count; i++) {
    
            NSString *temp = [NSString stringWithFormat:@"%@", temp_array[i]];
            CGFloat i_temp = [temp floatValue];
            
    //            NSLog(@"一天的温度😆😆 %.2f 😆😆", i_temp);
            if (i == 0) {
                maxTemp = i_temp;
                minTemp = i_temp;
            }
    
            if (maxTemp > i_temp) {
                maxTemp = maxTemp;
            } else {
                maxTemp = i_temp;
            }
            if (minTemp > i_temp) {
                minTemp = i_temp;
            } else {
                minTemp = minTemp;
            }
        }
        
        // 温度之差 的 温度范围:温度三种情况都是这个减法获取温度的范围
        CGFloat maxTempRange = maxTemp - minTemp;
        double maxTempRange_value = 0;
        if (maxTempRange == 0) {
            maxTempRange_value = 0;
        } else {
            maxTempRange_value = 70 / maxTempRange;
        }
        /** 最高温 path */
        UIBezierPath *weather_MaxTempPath = [UIBezierPath bezierPath];
        
        // 设置path的 起始点 和 其他点
        for (int k = 0; k < self.dailyWeathers.count; k++) {
            GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel = self.dailyWeathers[k];
            CGFloat nextTemp = [dailyWeatherModel.day_MaxTemp floatValue];
            
            // 两个相邻 端点 的位置间隔:67
            
            if (k == 0) { // 第一个,特殊处理
                // 第一个点,起始点。
                [weather_MaxTempPath moveToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width/375*67/2, [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (nextTemp - minTemp)))];
                
            } else {
                
                GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel0 = self.dailyWeathers[k-1];
                CGFloat lastTemp = [dailyWeatherModel0.day_MaxTemp floatValue];
                
                // 原理(这里的天气温度曲线):endPoint:下一个端点的x、y轴坐标, controlPoint1:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和上一个startPoint.y, controlPoint2:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和下一个endPoint.y,
                [weather_MaxTempPath addCurveToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k) , [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (nextTemp - minTemp)))
                            controlPoint1:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k - 67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (lastTemp - minTemp)))
                            controlPoint2:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k - 67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * ((nextTemp - minTemp))))];
            }
            
        }
        
        CAShapeLayer *maxTemp_Layer = [[CAShapeLayer alloc] init];
        // 线宽
        maxTemp_Layer.lineWidth = [UIScreen mainScreen].bounds.size.width/375*2;
        // 线条的颜色
        maxTemp_Layer.strokeColor = RGBA(255, 195, 85, 1).CGColor;
        // 背景填充色
        maxTemp_Layer.fillColor = [UIColor clearColor].CGColor;
        // 将UIBezierPath类转换成CGPath,类似于UIColor的CGColor
        maxTemp_Layer.path = [weather_MaxTempPath CGPath];
        [self.top_lineFatherLayer addSublayer:maxTemp_Layer];
        
        
        /** 最低温 path */
        UIBezierPath *weather_MinTempPath = [UIBezierPath bezierPath];
        
        // 设置path的 起始点 和 其他点
        for (int k = 0; k < self.dailyWeathers.count; k++) {
            GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel = self.dailyWeathers[k];
            CGFloat nextTemp = [dailyWeatherModel.day_MinTemp floatValue];
            
            // 两个相邻 端点 的位置间隔:67
            
            if (k == 0) { // 第一个,特殊处理
                // 第一个点,起始点。
                [weather_MinTempPath moveToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width/375*67/2, [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (nextTemp - minTemp)))];
                
            } else {
                
                GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel0 = self.dailyWeathers[k-1];
                CGFloat lastTemp = [dailyWeatherModel0.day_MinTemp floatValue];
                
                // 原理(这里的天气温度曲线):endPoint:下一个端点的x、y轴坐标, controlPoint1:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和上一个startPoint.y, controlPoint2:X轴坐标是上一个startPoint.x和下一个endPoint.x的中间X坐标位置,Y轴是和下一个endPoint.y,
                [weather_MinTempPath addCurveToPoint:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k) , [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (nextTemp - minTemp)))
                            controlPoint1:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k - 67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (lastTemp - minTemp)))
                            controlPoint2:CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*k - 67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * ((nextTemp - minTemp))))];
            }
            
        }
        
        CAShapeLayer *minTemp_Layer = [[CAShapeLayer alloc] init];
        // 线宽
        minTemp_Layer.lineWidth = [UIScreen mainScreen].bounds.size.width/375*2;
        // 线条的颜色
        minTemp_Layer.strokeColor = RGBA(84, 189, 255, 1).CGColor;
        // 背景填充色
        minTemp_Layer.fillColor = [UIColor clearColor].CGColor;
        // 将UIBezierPath类转换成CGPath,类似于UIColor的CGColor
        minTemp_Layer.path = [weather_MinTempPath CGPath];
        [self.top_lineFatherLayer addSublayer:minTemp_Layer];
        
        
        
        // 所有的曲线端点(小圆点)的位置:CGPoint
        NSMutableArray *max_circleArray = [NSMutableArray arrayWithCapacity:0];
        NSMutableArray *min_circleArray = [NSMutableArray arrayWithCapacity:0];
        for (int j = 0; j < self.dailyWeathers.count; j++) {
            
            GWCW_ClubWeather_DailyWeatherModel *dailyWeatherModel = self.dailyWeathers[j];
            CGFloat max_temp = [dailyWeatherModel.day_MaxTemp floatValue];
            CGFloat min_temp = [dailyWeatherModel.day_MinTemp floatValue];
            
            // 最高温
            if (j == 0) {
                
                // 端点位置CGPoint
                CGPoint circlePoint = CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (max_temp - minTemp)));
                
                NSValue* circleValue = [NSValue valueWithCGPoint:circlePoint];
                [max_circleArray addObject:circleValue];
            } else {
                CGPoint circlePoint = CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*j), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (max_temp - minTemp)));
                
                NSValue* circleValue = [NSValue valueWithCGPoint:circlePoint];
                [max_circleArray addObject:circleValue];
            }
            
            UILabel *max_TempL = [[UILabel alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/375*(67*j), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (max_temp - minTemp)), [UIScreen mainScreen].bounds.size.width/375*67, [UIScreen mainScreen].bounds.size.width/375*16)];
            max_TempL.text = [NSString stringWithFormat:@"%@", dailyWeatherModel.day_MaxTemp];
            max_TempL.textColor = RGBA(0, 0, 0, 0.45);
            max_TempL.textAlignment = NSTextAlignmentCenter;
            max_TempL.font = [UIFont systemFontOfSize:[UIScreen mainScreen].bounds.size.width/375*15 weight:UIFontWeightRegular];
            [self.top_LineRangeView addSubview:max_TempL];
            
            
            
            // 最低温
            if (j == 0) {
                
                // 端点位置CGPoint
                CGPoint circlePoint = CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (min_temp - minTemp)));
                
                NSValue* circleValue = [NSValue valueWithCGPoint:circlePoint];
                [min_circleArray addObject:circleValue];
            } else {
                CGPoint circlePoint = CGPointMake([UIScreen mainScreen].bounds.size.width/375*(67/2 + 67*j), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (min_temp - minTemp)));
                
                NSValue* circleValue = [NSValue valueWithCGPoint:circlePoint];
                [min_circleArray addObject:circleValue];
            }
            
            UILabel *min_TempL = [[UILabel alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/375*(67*j), [UIScreen mainScreen].bounds.size.width/375*(70 - maxTempRange_value * (min_temp - minTemp) + 16*2 + 1), [UIScreen mainScreen].bounds.size.width/375*67, [UIScreen mainScreen].bounds.size.width/375*16)];
            min_TempL.text = [NSString stringWithFormat:@"%@", dailyWeatherModel.day_MinTemp];
            min_TempL.textColor = RGBA(0, 0, 0, 0.45);
            min_TempL.textAlignment = NSTextAlignmentCenter;
            min_TempL.font = [UIFont systemFontOfSize:[UIScreen mainScreen].bounds.size.width/375*15 weight:UIFontWeightRegular];
            [self.top_LineRangeView addSubview:min_TempL];
           
        }
        
        self.top_CollectionView.hidden = NO;
        if (self.dailyWeathers.count > 0) {
            
            self.hourlyWeather = self.dailyWeathers[0].hourlyWeather;
            [self dayWeather:self.dailyWeathers[0]];
        }
        
        
    }
    

    相关文章

      网友评论

        本文标题:iOS ~ 贝塞尔曲线:二阶曲线图📈,ShapeLayer

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