//
|
// HDLArcScaleSeekBar.m
|
// HDL_Widget_iOS
|
//
|
// Created by HDL on 2019/11/12.
|
// Copyright © 2019 JLChen. All rights reserved.
|
//
|
|
#import "HDLArcScaleSeekBar.h"
|
#import "ScalePointData.h"
|
#import "HDLUtlisXM.h"
|
|
|
#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
|
#define APP_DEFAULT_ROUND_BORDER_COLOR HEXCOLOR(0xEAEAEB)
|
|
|
@interface HDLArcScaleSeekBar ()
|
|
/**是否正在移动*/
|
@property (nonatomic, assign) BOOL bTouchMove;
|
/**进度单位符号*/
|
@property (nonatomic, strong) NSString *mProgressBarUnitSring;
|
/**最小值*/
|
@property (nonatomic, assign) CGFloat mMinValue;
|
/**最大值*/
|
@property (nonatomic, assign) CGFloat mMaxValue;
|
/**渐变色开始颜色。*/
|
@property (nonatomic, strong) UIColor *startColor;
|
|
/**渐变色结束颜色。*/
|
@property (nonatomic, strong) UIColor *endColor;
|
/**开口角度*/
|
@property (nonatomic, assign) CGFloat mOpenAngle;
|
// 圆弧的起始角度
|
@property (nonatomic, assign) CGFloat mStartAngle;
|
// 圆弧的起始角度
|
@property (nonatomic, assign) CGFloat mEndAngle;
|
// 圆弧的经过总范围角度角度
|
@property (nonatomic, assign) CGFloat mSweepAngle;
|
// 渐变色。
|
@property (nonatomic, strong) UIColor *currentColor;
|
@property (nonatomic, strong) UIColor *currentWaveColor;
|
// 是否离线
|
@property (nonatomic, assign) BOOL isOffline;
|
|
|
@property (nonatomic, copy) NSMutableArray *pointArray;//not recommended
|
|
/**
|
进度渐变颜色数组
|
*/
|
@property (nonatomic, strong) NSArray *mArcProgressBarColors;
|
|
@end
|
|
|
@implementation HDLArcScaleSeekBar{
|
|
int _mMoveCount;
|
|
CGPoint _mCenterPoint; //圆心坐标
|
|
bool _bIsInArcProgress;
|
|
CGFloat mSeekBarHeight;
|
CGFloat mSeekBarWidth;
|
CGFloat mSeekBarRadius;
|
|
// 控件正方形边宽
|
CGFloat _mArcWidth;
|
CGFloat _mPercent;
|
CGFloat _mCornerRadius;
|
|
//******************背景圆******************
|
// 剪切圆的半径
|
int clipRadius;
|
// 波浪固定高度
|
int mWaveHeight;
|
//背景圆宽
|
CGFloat bgRoundWidth;
|
// 剪切圆的X坐标
|
CGFloat mRoundX;
|
// 背景圆到刻度的距离
|
CGFloat bgRoundPadding;
|
// 圆弧的半径
|
CGFloat mArcRadius;
|
|
//******************刻度******************
|
// 刻度线高
|
CGFloat mScaleLineHeight;
|
CGFloat mScaleLineHeightOut;
|
|
// 刻度线宽
|
CGFloat mScaleLineWidth;
|
// 刻度线之间间隔
|
CGFloat mLinePadding;
|
//刻度总数
|
int mLineCount;
|
// 当前进度的刻度线数
|
int mTargetCount;
|
//每格刻度的角度
|
CGFloat mAngle;
|
|
//******************波浪******************
|
CGFloat _mWaveStartX;
|
CGFloat _mWaveEndX;
|
CGFloat _waveStartY;
|
CGFloat _mWaveEndY;
|
|
CGFloat _waveA;
|
CGFloat mCycleFactorW;
|
|
|
|
}
|
|
-(instancetype)initWithFrame:(CGRect)frame{
|
self = [super initWithFrame:frame];
|
if (self) {
|
_isClickable = YES;
|
_mMoveCount = 0;
|
|
_mProgress = 16;
|
_mPercent = 0;
|
_mMaxValue = 35.0f;
|
_mMinValue = 16.0f;
|
_mCornerRadius = 0;
|
_mOpenAngle = 90;
|
mScaleLineWidth = 15;
|
// mLinePadding = 10;
|
mScaleLineHeight = 15;
|
mScaleLineHeightOut = mScaleLineHeight/4;
|
mScaleLineWidth = 2;
|
bgRoundWidth = 8;
|
bgRoundPadding = 16;
|
mRoundX = 0;
|
mLinePadding = 10;
|
|
mCycleFactorW = M_PI*2/self.bounds.size.width;
|
_waveStartY = self.bounds.size.width*3/4;
|
_mWaveStartX = 0;
|
_mWaveEndX = self.bounds.size.width;
|
_mWaveEndY = self.bounds.size.height;
|
_waveA = 15.0f ;
|
_pointArray = [NSMutableArray array];
|
|
|
_mProgressTextColor = [UIColor blackColor];
|
_mProgressTextSize = 20;
|
_mProgressBarUnitSring = @"℃";
|
_isProgressTextShow = YES;
|
_pathBackColor = APP_DEFAULT_ROUND_BORDER_COLOR;
|
|
_startColor = HEXCOLOR(0x495AF4);
|
_endColor = HEXCOLOR(0xAE50A8);
|
_mArcProgressBarColors = @[
|
(id) _startColor.CGColor,
|
(id)_endColor.CGColor
|
];
|
|
_currentColor = _startColor;
|
_currentWaveColor = [self getColorWithAlpha:_currentColor alpha:0.7f];
|
|
[self refreshFrame];
|
|
self.backgroundColor = [UIColor clearColor];
|
|
}
|
|
return self;
|
}
|
|
|
|
/**
|
刷新布局,更新关键值
|
|
*/
|
-(void)refreshFrame{
|
// _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
|
[self onArcSizeChange];
|
}
|
|
/**
|
刷新布局,更新关键值
|
|
*/
|
-(void)onArcSizeChange{
|
mSeekBarWidth = self.frame.size.width;
|
mSeekBarHeight = self.frame.size.height;
|
|
_mSweepAngle = 360 - _mOpenAngle;
|
_mStartAngle = 90 + _mOpenAngle/2;
|
_mEndAngle = GETEndAngle(_mOpenAngle/2);
|
_mArcWidth = MIN(mSeekBarWidth, mSeekBarHeight);
|
|
mCycleFactorW = M_PI*2/_mArcWidth;
|
|
// mArcRadius = (_mArcWidth - mScaleLineHeight)/2 ;
|
mArcRadius = _mArcWidth / 2 ;
|
_mCenterPoint = CGPointMake(_mArcWidth/2, _mArcWidth/2);
|
mRoundX = mScaleLineHeight + bgRoundPadding + mScaleLineHeightOut;
|
clipRadius = (int)(mArcRadius - mRoundX);
|
int ll = (int) ( _mSweepAngle * M_PI * mArcRadius) / 180;
|
mLineCount = (int)(ll / (mScaleLineWidth + mLinePadding));
|
mAngle = _mSweepAngle / mLineCount;
|
mWaveHeight = clipRadius / 3 ;
|
mTargetCount = (int)(_mPercent * mLineCount);
|
|
|
_mWaveStartX = mRoundX;
|
_mWaveEndX = mSeekBarWidth - _mWaveStartX;
|
//高为圆的6分之一左右
|
_waveStartY = _mArcWidth - mRoundX - clipRadius/3;
|
_mWaveEndY = mSeekBarHeight - _mWaveStartX;
|
|
[self loadScalePointArray];//更新刻度线坐标
|
|
}
|
|
|
-(void)loadScalePointArray{
|
[_pointArray removeAllObjects];
|
CGFloat nowAngle;
|
CGPoint p1;
|
CGPoint p2;
|
for (int i = 0; i <= mLineCount; i++) {
|
nowAngle = _mStartAngle + mAngle*i;
|
p1 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeightOut];
|
p2 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeight-mScaleLineHeightOut];
|
ScalePointData *mData = [[ScalePointData alloc] init];
|
mData.startPoint = p1;
|
mData.endPoint = p2;
|
|
[_pointArray addObject:mData];
|
}
|
}
|
|
|
|
|
#pragma mark drawRect 绘制图形
|
-(void)drawRect:(CGRect)rect{
|
[super drawRect:rect];
|
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
//将当前图形状态推入堆栈
|
CGContextSaveGState(ctx);
|
//*********绘制固定的背景圆弧*********
|
// [self drawBackArc:ctx];
|
// [self drawProgressBar2:ctx];
|
|
//********背景圆*********
|
[self drawRoundView:ctx r:rect];
|
//*********绘制动态的进度条*********
|
[self drawProgressBar:ctx];
|
|
// [self drawArcWithGradient:ctx rect:rect];//绘制渐变效果
|
//*********绘制显示进度值文字*********
|
[self drawProgressText:ctx];
|
//*********如果离线绘制离线背景遮挡层*********
|
[self drawOfflineView:ctx];
|
|
|
//把堆栈顶部的状态弹出
|
CGContextRestoreGState(ctx);
|
|
}
|
|
|
|
/**
|
如果离线绘制离线背景遮挡层
|
|
@param ctx 画布
|
*/
|
-(void)drawOfflineView:(CGContextRef)ctx{
|
if(_isOffline){
|
CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
|
UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
|
[APP_DEFAULT_OFFLINE_COLOR set];
|
CGContextAddPath(ctx, path3.CGPath);
|
CGContextDrawPath(ctx, kCGPathFill);
|
}
|
}
|
|
|
|
/**
|
绘制进度条
|
|
@param ctx 画布
|
*/
|
-(void)drawRoundView:(CGContextRef)ctx r:(CGRect)r{
|
|
//实线椭圆
|
//垂直居中
|
CGRect rectRing = CGRectMake(mRoundX, mRoundX, clipRadius*2, clipRadius*2);
|
|
// CGContextDrawPath(ctx, kCGPathFill);
|
//*******绘制剪裁限制显示区域*********
|
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:rectRing];
|
CGContextAddPath(ctx, path2.CGPath);
|
// 剪裁路径
|
CGContextClip(ctx);
|
//*******绘制波浪效果区域*********
|
[self drawWaveView:ctx number:0];
|
|
// [self drawWaveView:ctx number:1];
|
|
|
CGContextRestoreGState(ctx);// 恢复到之前的context
|
CGContextSaveGState(ctx);
|
|
CGContextSetLineWidth(ctx, bgRoundWidth);
|
CGContextSetStrokeColorWithColor(ctx, _pathBackColor.CGColor);
|
CGContextAddEllipseInRect(ctx, rectRing);
|
|
CGContextDrawPath(ctx, kCGPathStroke);
|
|
}
|
|
|
|
/*
|
y = Asin(ωx+φ)+k
|
A表示振幅,使用这个变量来调整波浪的高度
|
ω表示频率,使用这个变量来调整波浪密集度
|
φ表示初相,使用这个变量来调整波浪初始位置
|
k表示高度,使用这个变量来调整波浪在屏幕中y轴的位置。
|
*/
|
|
//正弦曲线公式:y=Asin(ωx+φ)+k
|
//
|
//A :振幅,曲线最高位和最低位的距离
|
//
|
//ω :角速度,用于控制周期大小,单位x中起伏的个数
|
//
|
//K :偏距,曲线上下偏移量
|
//
|
//φ :初相,曲线左右偏移量
|
|
-(void)drawWaveView:(CGContextRef)ctx number:(int)number{
|
|
CGContextBeginPath(ctx);
|
//1、添加第一点
|
CGContextMoveToPoint(ctx, _mWaveStartX, _waveStartY );
|
CGFloat y = _waveStartY ;
|
|
if(number > 0){
|
//2、添加水波浪效果,正玄函数 来计算每一个像素的坐标
|
for (int i = _mWaveStartX; i <= _mWaveEndX; ++i) {
|
y = _waveA * sin(mCycleFactorW * i+ 16) + _waveStartY ;
|
CGContextAddLineToPoint(ctx, i, y);
|
}
|
|
}else{
|
//2、添加水波浪效果,正玄函数 来计算每一个像素的坐标
|
for (int i = _mWaveStartX; i <= _mWaveEndX; ++i) {
|
y = _waveA * cos(mCycleFactorW * i + 5) + _waveStartY ;
|
CGContextAddLineToPoint(ctx, i, y);
|
}
|
|
}
|
CGContextAddLineToPoint(ctx, _mWaveEndX, _mWaveEndY);
|
CGContextAddLineToPoint(ctx, _mWaveStartX, _mWaveEndY);
|
|
|
// CGContextClosePath(ctx);
|
// CGContextSetFillColorWithColor(ctx, _currentWaveColor.CGColor );
|
// CGContextDrawPath(ctx, kCGPathFill);
|
|
[self drawArcWithGradient:ctx];
|
}
|
|
|
/**
|
绘制渐变效果
|
*/
|
-(void)drawArcWithGradient:(CGContextRef)ctx{
|
// 创建一个渐变色
|
// 创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mArcProgressBarColors, NULL);
|
// 释放色彩空间
|
CGColorSpaceRelease(colorSpace);
|
colorSpace = NULL;
|
|
// "反选路径"
|
// CGContextReplacePathWithStrokedPath
|
// 将context中的路径替换成路径的描边版本,使用参数context去计算路径(即创建新的路径是原来路径的描边)。用恰当的颜色填充得到的路径将产生类似绘制原来路径的效果。你可以像使用一般的路径一样使用它。例如,你可以通过调用CGContextClip去剪裁这个路径的描边
|
// CGContextReplacePathWithStrokedPath(ctx);
|
// // 剪裁路径
|
CGContextClip(ctx);
|
// CGRect drawRect2 = CGRectMake(_mWaveStartX, _waveStartY , clipRadius*2, _waveStartY );
|
// 用渐变色填充
|
CGContextDrawLinearGradient(ctx, gradient, CGPointMake(_mWaveStartX+30, _waveStartY), CGPointMake(_mArcWidth-_mWaveStartX-30, _mArcWidth), 0);
|
// 释放渐变色
|
CGGradientRelease(gradient);
|
gradient = NULL;
|
|
CGContextRestoreGState(ctx);// 恢复到之前的context
|
CGContextSaveGState(ctx);
|
}
|
|
/**
|
绘制固定的背景圆弧
|
|
@param ctx 画布
|
*/
|
-(void)drawBackArc:(CGContextRef)ctx{
|
|
|
//1.1 设置线条的宽度
|
CGContextSetLineWidth(ctx, mScaleLineHeight);
|
//1.2 设置线条的起始点样式
|
CGContextSetLineCap(ctx, kCGLineCapButt);
|
//1.3 虚实切换 ,实线5虚线10
|
CGFloat length[] = {mScaleLineWidth, mLinePadding};
|
CGContextSetLineDash(ctx, 0, length, 2);
|
//1.4 设置颜色
|
[_pathBackColor set];
|
//2.设置路径
|
CGContextAddArc(ctx, _mArcWidth/2 , _mArcWidth/2, mArcRadius, M_PI/180*_mStartAngle, M_PI/180*(_mEndAngle), 0);
|
//3.绘制
|
CGContextStrokePath(ctx);
|
|
|
}
|
|
|
/*
|
* 根据当前角度 计算出拖动按钮正确的圆心坐标
|
*/
|
-(CGPoint)getThumbCenterPointFromAngle:(int)angleInt rdius:(CGFloat)rdius{
|
CGPoint result;
|
result.y = round(_mCenterPoint.y + rdius * sin(ToRad(angleInt)));
|
result.x = round(_mCenterPoint.x + rdius * cos(ToRad(angleInt)));
|
return result;
|
}
|
|
/**
|
绘制刻度进度条
|
|
@param ctx 画布
|
*/
|
-(void)drawProgressBar:(CGContextRef)ctx{
|
if([_pointArray count] != mLineCount + 1) return;
|
|
for (int i = 0; i <= mLineCount; i++) {
|
|
UIBezierPath *linePath = [UIBezierPath bezierPath];
|
ScalePointData *mData = [_pointArray objectAtIndex:i];
|
|
if(i <= mTargetCount && mTargetCount != 0){
|
if(i == mTargetCount){
|
//最后一条刻度加长效果
|
CGFloat nowAngle = _mStartAngle + mAngle*i;
|
CGPoint p1 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius];
|
CGPoint p2 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeight-mScaleLineHeightOut];
|
[linePath moveToPoint:p1];
|
[linePath addLineToPoint:p2];
|
}else{
|
[linePath moveToPoint:mData.startPoint];
|
[linePath addLineToPoint:mData.endPoint];
|
|
}
|
CGContextSetLineWidth(ctx, mScaleLineWidth);
|
CGContextSetLineCap(ctx, kCGLineCapRound);
|
|
CGFloat mColorPercent = (CGFloat) i / mLineCount;
|
|
_currentColor = [self getGradientColor:mColorPercent];
|
_currentWaveColor = [self getColorWithAlpha:_currentColor alpha:0.7f];
|
|
[_currentColor setStroke];
|
} else {
|
[linePath moveToPoint:mData.startPoint];
|
[linePath addLineToPoint:mData.endPoint];
|
CGContextSetLineWidth(ctx, mScaleLineWidth);
|
CGContextSetLineCap(ctx, kCGLineCapRound);
|
//背景区间
|
[_pathBackColor setStroke];
|
}
|
CGContextAddPath(ctx, linePath.CGPath);
|
CGContextStrokePath(ctx);
|
|
}
|
|
|
|
|
|
// for (int i = 0; i < mLineCount; i++) {
|
//
|
// UIBezierPath *linePath = [UIBezierPath bezierPath];
|
// CGFloat nowAngle = _mStartAngle + mAngle*i;
|
// CGFloat decreaseValue = 0;
|
//
|
// // [linePath moveToPoint:CGPointMake(mArcRadius+(mArcRadius-decreaseValue)*cosf(nowAngle), mArcRadius+(mArcRadius-decreaseValue)*sinf(nowAngle))];
|
// // [linePath addLineToPoint:CGPointMake(mArcRadius+(mArcRadius-mScaleLineHeight)*cosf(nowAngle), mArcRadius+(mArcRadius-mScaleLineHeight)*sinf(nowAngle))];
|
// //
|
//
|
// CGPoint p1 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius];
|
// CGPoint p2 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeight];
|
//
|
// [linePath moveToPoint:p1];
|
// [linePath addLineToPoint:p2];
|
//
|
//
|
// CGContextSetLineWidth(ctx, mScaleLineWidth);
|
// CGContextSetLineCap(ctx, kCGLineCapRound);
|
//
|
// if(i <= mTargetCount && mTargetCount != 0){
|
//
|
// CGFloat mColorPercent = (CGFloat) i / mLineCount;
|
//
|
// _currentColor = [self getGradientColor:mColorPercent];
|
// _currentWaveColor = [self getColorWithAlpha:_currentColor alpha:0.7f];
|
//
|
// [_currentColor setStroke];
|
// } else {
|
// //背景区间
|
// [_pathBackColor setStroke];
|
// }
|
// CGContextAddPath(ctx, linePath.CGPath);
|
// CGContextStrokePath(ctx);
|
//
|
// }
|
|
}
|
|
///**
|
// 绘制刻度进度条
|
//
|
// @param ctx 画布
|
// */
|
//-(void)drawProgressBar2:(CGContextRef)ctx{
|
//
|
//
|
// //1.1 设置线条的宽度
|
// CGContextSetLineWidth(ctx, mScaleLineHeight);
|
// //1.2 设置线条的起始点样式
|
// CGContextSetLineCap(ctx, kCGLineCapButt);
|
// //1.3 虚实切换 ,实线5虚线10
|
// CGFloat length[] = {mScaleLineWidth, mLinePadding};
|
// CGContextSetLineDash(ctx, 0, length, 2);
|
//
|
// //1.4 设置颜色
|
// CGFloat mColorPercent = (CGFloat) 0 / mLineCount;
|
// _currentColor = [self getGradientColor:mColorPercent];
|
// [_currentColor setStroke];
|
//
|
//
|
// //2.设置路径
|
//
|
//// [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(numberChange:) name:@"number" object:nil];
|
//
|
// CGFloat end = -5*M_PI_4+(6*M_PI_4*_mProgress/100);
|
//
|
// CGContextAddArc(ctx, _mArcWidth/2 , _mArcWidth/2, mArcRadius,M_PI/180*_mStartAngle, end , 0);
|
//
|
// //3.绘制
|
// CGContextStrokePath(ctx);
|
//
|
//}
|
|
|
|
/**
|
绘制进度显示值文字
|
|
@param ctx 画布
|
*/
|
-(void)drawProgressText:(CGContextRef)ctx{
|
if(_isProgressTextShow){
|
[self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
|
}
|
}
|
|
|
|
|
|
|
|
/**
|
drawString 现在当前进度值
|
@param mText 显示文本
|
@param outsidePoint 坐标
|
*/
|
- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
|
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
|
paragraph.alignment = NSTextAlignmentCenter;
|
NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
|
NSForegroundColorAttributeName : _mProgressTextColor,
|
NSParagraphStyleAttributeName : paragraph
|
};
|
|
// CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
|
// [mText drawInRect:textRect withAttributes:dic];
|
|
//2019-08-15 修改文字绘制方法,最终实现文本居中效果
|
CGSize textSize = [mText sizeWithAttributes:dic];
|
CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//根据中点坐标绘制
|
[mText drawAtPoint:textPoint withAttributes:dic];
|
|
}
|
|
|
|
|
|
#pragma mark Touch Event 点击事件
|
-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
|
[super beginTrackingWithTouch:touch withEvent:event];
|
if(!_isClickable) return YES;//禁止点击
|
_bTouchMove = NO;
|
_mMoveCount = 0;
|
|
CGPoint startPoint = [touch locationInView:self];
|
_bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//判断开始坐标是否在可点击区域
|
|
|
// _bIsInArcProgress = YES;//不限制点击区域
|
if(_bIsInArcProgress){
|
[self.mProgressChangedDelegate onStartTrackingTouch];
|
}
|
return YES;
|
}
|
|
-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
|
[super endTrackingWithTouch:touch withEvent:event];
|
if(!_isClickable) return;//禁止点击
|
if(!_bTouchMove){//没移动,仅点击
|
if(_bIsInArcProgress){
|
CGPoint lastPoint = [touch locationInView:self];
|
[self getCurrentProgressWithLastPoint:lastPoint];
|
[self sendActionsForControlEvents:UIControlEventValueChanged];
|
}
|
}
|
if(_bIsInArcProgress){
|
[self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
|
}
|
}
|
|
|
-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
|
[super continueTrackingWithTouch:touch withEvent:event];
|
if(!_isClickable) return YES;//禁止点击
|
if(_mMoveCount < 2){
|
_mMoveCount++;
|
}else{
|
_bTouchMove = YES; //开始移动
|
}
|
|
if(_bIsInArcProgress){//如果刚开始点击的坐标在可点击区域
|
CGPoint lastPoint = [touch locationInView:self];
|
[self getCurrentProgressWithLastPoint:lastPoint];
|
}
|
[self sendActionsForControlEvents:UIControlEventValueChanged];
|
return YES;
|
}
|
|
static inline CGFloat AngleFromNorth(CGPoint p1, CGPoint p2, BOOL flipped) {
|
CGPoint v = CGPointMake(p2.x-p1.x,p2.y-p1.y);
|
CGFloat vmag = sqrt(SQR(v.x) + SQR(v.y)), result = 0;
|
v.x /= vmag;
|
v.y /= vmag;
|
double radians = atan2(v.y,v.x);
|
result = ToDeg(radians);
|
return (result >=0 ? result : result + 360.0);
|
}
|
|
|
-(void)getCurrentAngleWithPoint:(CGPoint)point {
|
|
|
}
|
|
/*
|
* 判断坐标是否在可点击区域
|
*/
|
-(BOOL)getStartPointIsInArcProgress:(CGPoint)lastPoint {
|
BOOL isIn = NO;
|
//用于排除点在圆外面点与圆心半径一半以内的点
|
if ((lastPoint.x >= 0 && lastPoint.x <= mSeekBarWidth)&&(lastPoint.y >= 0 && lastPoint.y <= mSeekBarHeight)) {
|
if ([self getTwoPointDistance:lastPoint endPonit:_mCenterPoint] > (mArcRadius - mRoundX)) {
|
isIn = YES;
|
}
|
}
|
return isIn;
|
}
|
|
/**
|
计算2点坐标之间的距离
|
|
@param startPoint 起点坐标
|
@param endPonit 终点坐标
|
@return 距离
|
*/
|
-(float) getTwoPointDistance:(CGPoint)startPoint endPonit:(CGPoint)endPonit{
|
CGPoint v = CGPointMake(startPoint.x - endPonit.x, startPoint.y - endPonit.y);
|
float d = sqrt(SQR(v.x) + SQR(v.y));
|
// NSLog(@"2点距离:%f ", d);
|
// NSLog(@"getTwoPointDistance2点距离:%f ", d);
|
return d;
|
|
}
|
|
/**
|
根据坐标计算出当前进度百分比和对应的进度值
|
|
@param point 当前坐标
|
*/
|
-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
|
|
|
CGFloat currentAngle = floor(AngleFromNorth(_mCenterPoint, point, NO));
|
|
//判断是否在符合角度
|
if(currentAngle < _mStartAngle-10 && currentAngle > _mEndAngle+10){
|
return;
|
}
|
|
int diffAngle = currentAngle - _mStartAngle;
|
|
|
if (diffAngle < 0) {
|
if(currentAngle < 90) {
|
diffAngle = (diffAngle + 360) % 360;
|
}else {
|
diffAngle = 0;
|
}
|
}
|
|
_mPercent = diffAngle / _mSweepAngle;
|
|
|
// NSLog(@"point.y:%f currentAngle:%f diffAngle:%d",point.x, currentAngle,diffAngle);
|
|
if(_mPercent > 1){
|
_mPercent = 1;
|
}else if(_mPercent < 0){
|
_mPercent = 0;
|
}
|
|
_mProgress = _mPercent * (_mMaxValue - _mMinValue) + _mMinValue;
|
|
mTargetCount = (int)(_mPercent * mLineCount);
|
|
|
|
if(_bTouchMove){
|
[self.mProgressChangedDelegate onProgressChanged:_mProgress];
|
}
|
|
[self setNeedsDisplay];
|
}
|
|
|
/**
|
根据进度值,计算当前 _mProgressAngle值
|
|
@param mProgress 进度值
|
*/
|
-(void)setSeekBarProgressToValue:(int)mProgress{
|
if(mProgress < _mMinValue){
|
mProgress = _mMinValue;
|
}
|
if(mProgress > _mMaxValue){
|
mProgress = _mMaxValue;
|
}
|
_mProgress = mProgress;
|
_mPercent = (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
|
|
mTargetCount = (int)(_mPercent * mLineCount);
|
|
// [self.mProgressChangedDelegate onProgressChanged:_mProgress];
|
}
|
|
|
|
|
#pragma mark 设置进度条位置
|
/**
|
设置进度值
|
|
@param mProgress 进度值
|
*/
|
-(void)setProgress:(int)mProgress{
|
[self setSeekBarProgressToValue:mProgress];
|
[self setNeedsDisplay];
|
}
|
|
|
/**
|
设置进度显示值单位
|
|
@param mString 单位字符
|
*/
|
-(void)setProgressBarUnitSring:(NSString *)mString{
|
_mProgressBarUnitSring = mString;
|
}
|
|
|
/**
|
设置最大值最小值
|
|
@param mMinValue 最小值
|
@param mMaxValue 最大值
|
*/
|
-(void)setMinAndMaxValue:(CGFloat)mMinValue mMaxValue:(CGFloat)mMaxValue{
|
if(mMinValue < mMaxValue){
|
_mMinValue = mMinValue;
|
_mMaxValue = mMaxValue;
|
}else{
|
_mMinValue = mMaxValue;
|
_mMaxValue = mMinValue;
|
}
|
_mProgress = _mMinValue;
|
_mPercent = 0.0f;
|
}
|
|
|
/**
|
重置布局
|
|
@param mCGRect 布局
|
|
*/
|
-(void)initWithFrameSeekBar:(CGRect) mCGRect{
|
self.frame = mCGRect;
|
[self refreshFrame];
|
}
|
|
|
|
/**
|
设置是否离线
|
*/
|
-(void)setOffline:(BOOL)isOffline{
|
_isOffline = isOffline;
|
_isClickable = !_isOffline;
|
[self setNeedsDisplay];
|
}
|
|
|
|
//获取当前颜色
|
- (UIColor *)getGradientColor:(CGFloat)current {
|
|
CGFloat c1[4];
|
CGFloat c2[4];
|
|
[_startColor getRed:&c1[0] green:&c1[1] blue:&c1[2] alpha:&c1[3]];
|
[_endColor getRed:&c2[0] green:&c2[1] blue:&c2[2] alpha:&c2[3]];
|
|
return [UIColor colorWithRed:current*c2[0]+(1-current)*c1[0] green:current*c2[1]+(1-current)*c1[1] blue:current*c2[2]+(1-current)*c1[2] alpha:current*c2[3]+(1-current)*c1[3]];
|
}
|
|
//获取当前颜色
|
- (UIColor *)getColorWithAlpha:(UIColor*)mColor alpha:(CGFloat)alpha {
|
CGFloat c1[4];
|
[mColor getRed:&c1[0] green:&c1[1] blue:&c1[2] alpha:&c1[3]];
|
return [UIColor colorWithRed:c1[0] green:c1[1] blue:c1[2] alpha:alpha];
|
}
|
|
|
/**
|
设置渐变效果
|
|
@param startColor 开始颜色
|
@param endColor 结束颜色
|
*/
|
-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
|
_startColor = startColor;
|
_endColor = endColor;
|
_mArcProgressBarColors = @[
|
(id)startColor.CGColor,
|
(id)endColor.CGColor
|
];
|
|
}
|
|
@end
|