【问题标题】:draw embossed arc using core graphics使用核心图形绘制浮雕弧
【发布时间】:2012-05-02 16:36:54
【问题描述】:

我正在尝试实现一个自定义滑块,如下图所示。

到目前为止我所做的看起来像这样

请帮我画出这种效果的弧线。我的代码如下,我正在做的是使用线宽为 kLineWidth 的 CGContextAddArc 绘制弧线。

- (void)drawThumbAtPoint:(CGPoint)sliderButtonCenterPoint inContext: (CGContextRef)context {
UIGraphicsPushContext(context);
CGContextBeginPath(context);

CGContextMoveToPoint(context, sliderButtonCenterPoint.x, sliderButtonCenterPoint.y);

CGImageRef imageRef = [UIImage imageNamed:@"circle25.png"].CGImage;
CGRect rect = CGRectMake(sliderButtonCenterPoint.x - kThumbRadius, sliderButtonCenterPoint.y - kThumbRadius, kThumbRadius*2, kThumbRadius*2);
CGContextDrawImage(context, rect, imageRef);

//CGContextAddArc(context, sliderButtonCenterPoint.x, sliderButtonCenterPoint.y, kThumbRadius, 0.0, 2*M_PI, NO);

CGContextFillPath(context);
UIGraphicsPopContext();
}

- (CGPoint)drawArcTrack:(float)track atPoint:(CGPoint)center withRadius:(CGFloat)radius inContext:(CGContextRef)context {
UIGraphicsPushContext(context);
CGContextBeginPath(context);

float angleFromTrack = translateValueFromSourceIntervalToDestinationInterval(track, self.minimumValue, self.maximumValue, 0, M_PI/3);// 2*M_PI

CGFloat startAngle = (4*M_PI)/3;
CGFloat endAngle = startAngle + angleFromTrack;

CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, NO);

CGPoint arcEndPoint = CGContextGetPathCurrentPoint(context);

CGContextStrokePath(context);   

UIGraphicsPopContext();

return arcEndPoint;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGPoint middlePoint;
    middlePoint.x = self.bounds.origin.x + self.bounds.size.width/2;
middlePoint.y = self.bounds.origin.y + self.bounds.size.width;

CGContextSetLineWidth(context, kLineWidth);

CGFloat radius = [self sliderRadius];


[self.maximumTrackTintColor setStroke];         
[self drawArcTrack:self.maximumValue atPoint:middlePoint withRadius:radius inContext:context];          
[self.minimumTrackTintColor setStroke];         
self.thumbCenterPoint = [self drawArcTrack:self.value atPoint:middlePoint withRadius:radius inContext:context];     

[self.thumbTintColor setFill];
[self drawThumbAtPoint:self.thumbCenterPoint inContext:context];
}

【问题讨论】:

    标签: iphone ios core-graphics


    【解决方案1】:

    除非您要动态更改形状,否则最好在图像编辑器中创建图像。我知道在 Photoshop、Illustrator 或 Fireworks 中创建这种效果很容易。

    也就是说,使用 Core Graphics 绘制像这样的内部阴影需要几个步骤:

    1. 剪辑到形状(例如使用CGContextClipCGContextClipToMask)。
    2. 形状之外的所有内容创建路径或蒙版。
    3. 设置阴影参数(使用CGContextSetShadowWithColor)。
    4. 填充第 2 步中的路径或蒙版。这会在形状内部投射阴影,并且仅绘制阴影,因为您在第 1 步中剪裁了形状。

    如果你做的都正确,你会得到一个像这样的好结果:

    这是我为绘制它而编写的代码。我在自定义视图子类的drawRect: 中编写了它,但是您可以轻松地使用此代码绘制到任何图形上下文中。

    - (void)drawRect:(CGRect)rect {
        CGContextRef gc = UIGraphicsGetCurrentContext();
    

    首先,我创建一个只是弧的路径:

        static CGFloat const kArcThickness = 20.0f;
        CGRect arcBounds = CGRectInset(self.bounds, 10.0f, 10.0f);
        CGPoint arcCenter = CGPointMake(CGRectGetMidX(arcBounds), CGRectGetMidY(arcBounds));
        CGFloat arcRadius = 0.5f * (MIN(arcBounds.size.width, arcBounds.size.height) - kArcThickness);
        UIBezierPath *arc = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:arcRadius startAngle:-M_PI / 3.0 endAngle:-2.0 * M_PI / 3.0 clockwise:NO];
    

    接下来,我要求 Core Graphics 创建一个新路径,即arc 路径的轮廓。请注意我如何要求它提供kArcThickness 的笔画宽度和圆形线帽:

        CGPathRef shape = CGPathCreateCopyByStrokingPath(arc.CGPath, NULL, kArcThickness, kCGLineCapRound, kCGLineJoinRound, 10.0f);
    

    我还需要该路径的倒数:包含每个点除了shape 中的点的路径。碰巧(尽管我认为没有记录)CGContextCreateCopyByStrokingPathCGPathAddRect 朝相反的方向绘制。因此,如果我复制shape 并在其周围画一个巨大的矩形,非零缠绕规则意味着新路径将是shape 的倒数:

        CGMutablePathRef shapeInverse = CGPathCreateMutableCopy(shape);
        CGPathAddRect(shapeInverse, NULL, CGRectInfinite);
    

    现在我可以开始画画了。首先,我将用浅灰色填充形状:

        CGContextBeginPath(gc);
        CGContextAddPath(gc, shape);
        CGContextSetFillColorWithColor(gc, [UIColor colorWithWhite:.9 alpha:1].CGColor);
        CGContextFillPath(gc);
    

    接下来我实际执行上面列出的四个步骤。我必须保存图形状态,以便在完成后撤消裁剪和阴影参数。

        CGContextSaveGState(gc); {
    

    第 1 步:剪辑到形状:

            CGContextBeginPath(gc);
            CGContextAddPath(gc, shape);
            CGContextClip(gc);
    

    第 2 步:嗯,我在创建 shapeInverse 时已经完成了这一步。

    第三步:我设置阴影参数:

            CGContextSetShadowWithColor(gc, CGSizeZero, 7, [UIColor colorWithWhite:0 alpha:.25].CGColor);
    

    第 4 步:我填充第 2 步中的反转形状:

            CGContextBeginPath(gc);
            CGContextAddPath(gc, shapeInverse);
            CGContextFillPath(gc);
    

    现在我恢复图形状态,专门恢复剪切路径并取消设置阴影参数。

        } CGContextRestoreGState(gc);
    

    最后,我会用浅灰色描边shape,让边缘更清晰:

        CGContextSetStrokeColorWithColor(gc, [UIColor colorWithWhite:.75 alpha:1].CGColor);
        CGContextSetLineWidth(gc, 1);
        CGContextSetLineJoin(gc, kCGLineCapRound);
        CGContextBeginPath(gc);
        CGContextAddPath(gc, shape);
        CGContextStrokePath(gc);
    

    完成后我当然会清理:

        CGPathRelease(shape);
        CGPathRelease(shapeInverse);
    }
    

    更复杂的形状可以看my answer heremy answer here

    下面是所有代码,方便复制:

    - (void)drawRect:(CGRect)rect {
        CGContextRef gc = UIGraphicsGetCurrentContext();
    
        static CGFloat const kArcThickness = 20.0f;
        CGRect arcBounds = CGRectInset(self.bounds, 10.0f, 10.0f);
        CGPoint arcCenter = CGPointMake(CGRectGetMidX(arcBounds), CGRectGetMidY(arcBounds));
        CGFloat arcRadius = 0.5f * (MIN(arcBounds.size.width, arcBounds.size.height) - kArcThickness);
        UIBezierPath *arc = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:arcRadius startAngle:-M_PI / 3.0 endAngle:-2.0 * M_PI / 3.0 clockwise:NO];
        CGPathRef shape = CGPathCreateCopyByStrokingPath(arc.CGPath, NULL, kArcThickness, kCGLineCapRound, kCGLineJoinRound, 10.0f);
        CGMutablePathRef shapeInverse = CGPathCreateMutableCopy(shape);
        CGPathAddRect(shapeInverse, NULL, CGRectInfinite);
    
        CGContextBeginPath(gc);
        CGContextAddPath(gc, shape);
        CGContextSetFillColorWithColor(gc, [UIColor colorWithWhite:.9 alpha:1].CGColor);
        CGContextFillPath(gc);
    
        CGContextSaveGState(gc); {
            CGContextBeginPath(gc);
            CGContextAddPath(gc, shape);
            CGContextClip(gc);
            CGContextSetShadowWithColor(gc, CGSizeZero, 7, [UIColor colorWithWhite:0 alpha:.25].CGColor);
            CGContextBeginPath(gc);
            CGContextAddPath(gc, shapeInverse);
            CGContextFillPath(gc);
        } CGContextRestoreGState(gc);
    
        CGContextSetStrokeColorWithColor(gc, [UIColor colorWithWhite:.75 alpha:1].CGColor);
        CGContextSetLineWidth(gc, 1);
        CGContextSetLineJoin(gc, kCGLineCapRound);
        CGContextBeginPath(gc);
        CGContextAddPath(gc, shape);
        CGContextStrokePath(gc);
    
        CGPathRelease(shape);
        CGPathRelease(shapeInverse);
    }
    

    【讨论】:

    • 效果很好!非常感谢。我需要做的一件事是将 self.backgroundColor 设置为在具有 drawRect 魔法的自定义 uiview 子类中清除。
    • @Shashank 你能在那个路径上移动那个滑块吗?你能分享你的代码吗?
    • @NSIllusion 查看this answer,了解将可拖动对象约束到路径的通用解决方案。
    • @robmayoffThanks.great post.
    • 方便复制粘贴的主要措施
    【解决方案2】:

    检查以下代码以了解上述组件的完整功能版本,它的工作原理(可能有点混乱)。

    #import "UIArcSlider.h"
    
    @interface UIArcSlider()
    
    @property (nonatomic) CGPoint thumbCenterPoint;
    
    #pragma mark - Init and Setup methods
    - (void)setup;
    
    #pragma mark - Thumb management methods
    - (BOOL)isPointInThumb:(CGPoint)point;
    
    #pragma mark - Drawing methods
    - (CGFloat)sliderRadius;
    - (void)drawThumbAtPoint:(CGPoint)sliderButtonCenterPoint inContext:(CGContextRef)context;
    - (CGPoint)drawTheArcTrack:(float)track atPoint:(CGPoint)center withRadius:(CGFloat)radius AndColor:(Boolean) isWhite inContext:(CGContextRef)context;
    - (CGPoint)drawTheLineTrack:(float)track withColor:(Boolean) isWhite inContext:(CGContextRef)context;
    
    @end
    
    #pragma mark -
    @implementation UIArcSlider
    
    @synthesize sliderStyle = _sliderStyle;
    - (void)setSliderStyle:(UISliderStyle)sliderStyle {
        if (sliderStyle != _sliderStyle) {
            _sliderStyle = sliderStyle;
            [self setNeedsDisplay];
        }
    }
    
    @synthesize value = _value;
    - (void)setValue:(float)value {
        if (value != _value) {
            if (value > self.maximumValue) { value = self.maximumValue; }
            if (value < self.minimumValue) { value = self.minimumValue; }
            _value = value;
            [self setNeedsDisplay];
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
    }
    @synthesize minimumValue = _minimumValue;
    - (void)setMinimumValue:(float)minimumValue {
        if (minimumValue != _minimumValue) {
            _minimumValue = minimumValue;
            if (self.maximumValue < self.minimumValue)  { self.maximumValue = self.minimumValue; }
            if (self.value < self.minimumValue)         { self.value = self.minimumValue; }
        }
    }
    @synthesize maximumValue = _maximumValue;
    - (void)setMaximumValue:(float)maximumValue {
        if (maximumValue != _maximumValue) {
            _maximumValue = maximumValue;
            if (self.minimumValue > self.maximumValue)  { self.minimumValue = self.maximumValue; }
            if (self.value > self.maximumValue)         { self.value = self.maximumValue; }
        }
    }
    
    @synthesize thumbCenterPoint = _thumbCenterPoint;
    
    /** @name Init and Setup methods */
    #pragma mark - Init and Setup methods
    - (id)initWithFrame:(CGRect)frame {
        self = [super initWithFrame:frame];
        if (self) {
            [self setup];
        } 
        return self;
    }
    - (void)awakeFromNib {
        [self setup];
    }
    
    - (void)setup {
        self.value = 0.0;
        self.minimumValue = 0.0;
        self.maximumValue = 100.0;
        self.thumbCenterPoint = CGPointZero;
    
        UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureHappened:)];
        [self addGestureRecognizer:tapGestureRecognizer];
    
        UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureHappened:)];
        panGestureRecognizer.maximumNumberOfTouches = panGestureRecognizer.minimumNumberOfTouches;
        [self addGestureRecognizer:panGestureRecognizer];
    }
    
    /** @name Drawing methods */
    #pragma mark - Drawing methods
    #define kLineWidth 22.0
    #define kThumbRadius 20.0
    #define kPadding 20.0
    
    - (CGFloat)sliderRadius {
        CGFloat radius = self.bounds.size.width;
        radius -= MAX(kLineWidth + kPadding, kThumbRadius  + kPadding); 
        return radius;
    }
    
    -(CGFloat)sliderWidth {    
        return self.bounds.size.width - kThumbRadius*2;
    }
    
    - (void)drawThumbAtPoint:(CGPoint)sliderButtonCenterPoint inContext:(CGContextRef)context {
        UIGraphicsPushContext(context);
        CGContextBeginPath(context);    
    
        CGContextMoveToPoint(context, sliderButtonCenterPoint.x, sliderButtonCenterPoint.y);
    
        CGRect rect = CGRectMake(sliderButtonCenterPoint.x - kThumbRadius, sliderButtonCenterPoint.y - kThumbRadius, kThumbRadius*2, kThumbRadius*2);
        CGImageRef imageRef = [UIImage imageNamed:@"circle25.png"].CGImage;
    
        CGContextDrawImage(context, rect, imageRef);
    
        UIGraphicsPopContext();        
    }
    
    - (CGPoint)drawTheArcTrack:(float)track atPoint:(CGPoint)center withRadius:(CGFloat)radius AndColor:(Boolean) isWhite inContext:(CGContextRef)context 
    {
        static CGFloat const kArcThickness = kLineWidth;
        CGPoint arcCenter = center;
        CGFloat arcRadius = radius;
    
        float angleFromTrack = translateValueFromSourceIntervalToDestinationInterval(track, self.minimumValue, self.maximumValue, 0, M_PI/3);// 2*M_PI
    
        CGFloat startAngle = (4*M_PI)/3;
        CGFloat endAngle = startAngle + angleFromTrack;
    
        UIBezierPath *arc = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:arcRadius startAngle:startAngle endAngle:endAngle clockwise:YES];
    
        CGPathRef shape = CGPathCreateCopyByStrokingPath(arc.CGPath, NULL, kArcThickness, kCGLineCapRound, kCGLineJoinRound, 10.0f);
        CGMutablePathRef shapeInverse = CGPathCreateMutableCopy(shape);
        CGPathAddRect(shapeInverse, NULL, CGRectInfinite);
    
        CGPoint arcEndPoint = [arc currentPoint];
    
        CGContextBeginPath(context);
        CGContextAddPath(context, shape);
    
        if (isWhite) {
            CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:.9 alpha:1].CGColor);
        } else {//70,172, 220
            CGContextSetFillColorWithColor(context, [UIColor colorWithRed:70/255.0 green:172/255.0 blue:220/255.0 alpha:1].CGColor);
        }    
    
        CGContextFillPath(context);
    
        CGContextSaveGState(context); {
            CGContextBeginPath(context);
            CGContextAddPath(context, shape);
            CGContextClip(context);
            if (isWhite) {
                CGContextSetShadowWithColor(context, CGSizeZero, 7, [UIColor colorWithWhite:0 alpha:.25].CGColor);
            } else {
                CGContextSetShadowWithColor(context, CGSizeZero, 7, [UIColor colorWithRed:85/255.0 green:183/255.0 blue:230/255.0 alpha:.25].CGColor);
            }       
            CGContextBeginPath(context);
            CGContextAddPath(context, shapeInverse);
            CGContextFillPath(context);
        } CGContextRestoreGState(context);
    
        if (isWhite) {
            CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:.75 alpha:1].CGColor);
        } else {
            CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:62/255.0 green:135/255.0 blue:169/255.0 alpha:1].CGColor);
        }
    
        CGContextSetLineWidth(context, 1);
        CGContextSetLineJoin(context, kCGLineCapRound);
        CGContextBeginPath(context);
        CGContextAddPath(context, shape);
        CGContextStrokePath(context);
    
        CGPathRelease(shape);
        CGPathRelease(shapeInverse);        
    
        return arcEndPoint;    
    }
    
    
    - (CGPoint)drawTheLineTrack:(float)track withColor:(Boolean) isWhite inContext:(CGContextRef)context
    {        
        CGFloat sliderWidth = [self sliderWidth];
        CGFloat xStart = self.bounds.origin.x + (self.bounds.size.width - sliderWidth)/2;
        CGFloat lineRectX = (self.bounds.size.width - sliderWidth)/2;
        CGFloat lineThickness = kLineWidth/2;
        CGFloat lineRectY = (self.bounds.size.height - lineThickness)/2;
    
        CGFloat xPoint = translateValueToPoint(track, xStart, self.maximumValue, sliderWidth);
        sliderWidth = xPoint;
    
        CGRect lineRect = CGRectMake(lineRectX, lineRectY, sliderWidth, lineThickness);
        UIBezierPath *line = [UIBezierPath bezierPathWithRoundedRect:lineRect cornerRadius:lineThickness/2];
    
        CGPathRef shape = CGPathCreateCopyByStrokingPath(line.CGPath, NULL, lineThickness, kCGLineCapRound, kCGLineJoinRound, 10.0f);
        CGMutablePathRef shapeInverse = CGPathCreateMutableCopy(shape);
        CGPathAddRect(shapeInverse, NULL, CGRectInfinite);
    
        CGPoint arcEndPoint = CGPointMake(lineRectX + xPoint, lineRectY + (lineThickness/2));
    
        CGContextBeginPath(context);
        CGContextAddPath(context, shape);
    
        if (isWhite) {
            CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:.9 alpha:1].CGColor);
        } else {//70,172, 220
            CGContextSetFillColorWithColor(context, [UIColor colorWithRed:70/255.0 green:172/255.0 blue:220/255.0 alpha:1].CGColor);
        }    
    
        CGContextFillPath(context);
    
        CGContextSaveGState(context); {
            CGContextBeginPath(context);
            CGContextAddPath(context, shape);
            CGContextClip(context);
            if (isWhite) {
                CGContextSetShadowWithColor(context, CGSizeZero, 7, [UIColor colorWithWhite:0 alpha:.25].CGColor);
            } else {
                CGContextSetShadowWithColor(context, CGSizeZero, 7, [UIColor colorWithRed:85/255.0 green:183/255.0 blue:230/255.0 alpha:.25].CGColor);
            }       
            CGContextBeginPath(context);
            CGContextAddPath(context, shapeInverse);
            CGContextFillPath(context);
        } CGContextRestoreGState(context);
    
        if (isWhite) {
            CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:.75 alpha:1].CGColor);
        } else {
            CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:62/255.0 green:135/255.0 blue:169/255.0 alpha:1].CGColor);
        }
    
        CGRect outlineRect = CGRectMake(lineRectX - (lineThickness/2), lineRectY - (lineThickness/2), sliderWidth + lineThickness, lineThickness * 2);
        UIBezierPath *outline = [UIBezierPath bezierPathWithRoundedRect:outlineRect cornerRadius:lineThickness];
        CGContextSetLineWidth(context, 1);
        CGContextSetLineJoin(context, kCGLineCapSquare);
        CGContextBeginPath(context);
        CGContextAddPath(context, outline.CGPath);
        CGContextStrokePath(context);
    
        CGPathRelease(shape);
        CGPathRelease(shapeInverse);        
    
        return arcEndPoint;    
    }
    
    - (void)drawRect:(CGRect)rect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGPoint middlePoint;
    
        switch (self.sliderStyle) {
            case UISliderStyleLine:
    
                [self drawTheLineTrack:self.maximumValue withColor:YES inContext:context];
                self.thumbCenterPoint = [self drawTheLineTrack:self.value withColor:NO inContext:context];
    
                [self drawThumbAtPoint:self.thumbCenterPoint inContext:context];
                break;
    
            case UISliderStyleArc:
            default:
                middlePoint.x = self.bounds.origin.x + self.bounds.size.width/2;
                middlePoint.y = self.bounds.origin.y + self.bounds.size.width;
    
                CGFloat radius = [self sliderRadius];                
                [self drawTheArcTrack:self.maximumValue atPoint:middlePoint withRadius:radius AndColor:YES inContext:context];
    
                self.thumbCenterPoint = [self drawTheArcTrack:self.value atPoint:middlePoint withRadius:radius AndColor:NO inContext:context];  
    
                [self drawThumbAtPoint:self.thumbCenterPoint inContext:context];
                break;
        }
    }
    
    /** @name Thumb management methods */
    #pragma mark - Thumb management methods
    - (BOOL)isPointInThumb:(CGPoint)point {
        CGRect thumbTouchRect = CGRectMake(self.thumbCenterPoint.x - kThumbRadius, self.thumbCenterPoint.y - kThumbRadius, kThumbRadius*2, kThumbRadius*2);
        return CGRectContainsPoint(thumbTouchRect, point);
    }
    
    /** @name UIGestureRecognizer management methods */
    #pragma mark - UIGestureRecognizer management methods
    - (void)panGestureHappened:(UIPanGestureRecognizer *)panGestureRecognizer {
        CGPoint tapLocation = [panGestureRecognizer locationInView:self];
        switch (panGestureRecognizer.state) {
            case UIGestureRecognizerStateChanged: {
    
                CGFloat radius;
                CGPoint sliderCenter;
                CGPoint sliderStartPoint;
                CGFloat angle;
    
    
                CGFloat xStart;
                CGFloat maximumValue;
                CGFloat sliderWidth;
                CGFloat point;
    
                switch (self.sliderStyle) {
                    case UISliderStyleLine:
    
                        sliderWidth = [self sliderWidth];
                        xStart = self.bounds.origin.x + (self.bounds.size.width - sliderWidth)/2;
                        maximumValue = self.maximumValue;
                        point = tapLocation.x;
    
                        self.value = translatePointToValue(point, xStart, maximumValue, sliderWidth);
    
                        break;
    
                    case UISliderStyleArc:
                    default:
    
                        radius = [self sliderRadius];
                        sliderCenter = CGPointMake(self.bounds.size.width/2, self.bounds.size.width);
                        sliderStartPoint = CGPointMake(sliderCenter.x - (radius * 1.15), sliderCenter.y - (radius * 2.1) );
                        angle = angleBetweenThreePoints(sliderCenter, sliderStartPoint, tapLocation);
    
                        if (angle < 0) {
                            angle = -angle;
                        }
                        else {
                            angle = 0.0;
                            //angle = M_PI/3 - angle;
                        }
    
                        self.value = translateValueFromSourceIntervalToDestinationInterval(angle, 0, M_PI/3, self.minimumValue, self.maximumValue);
                        break;
                }
            }
            default:
                break;
        }
    }
    - (void)tapGestureHappened:(UITapGestureRecognizer *)tapGestureRecognizer {
        if (tapGestureRecognizer.state == UIGestureRecognizerStateEnded) {
            CGPoint tapLocation = [tapGestureRecognizer locationInView:self];
            if ([self isPointInThumb:tapLocation]) {
                // do something on tap
            }
            else {
            }
        }
    }
    
    @end
    
    /** @name Utility Functions */
    #pragma mark - Utility Functions
    float translateValueFromSourceIntervalToDestinationInterval(float sourceValue, float sourceIntervalMinimum, float sourceIntervalMaximum, float destinationIntervalMinimum, float destinationIntervalMaximum) {
        float a, b, destinationValue;
    
        a = (destinationIntervalMaximum - destinationIntervalMinimum) / (sourceIntervalMaximum - sourceIntervalMinimum);
        b = destinationIntervalMaximum - a*sourceIntervalMaximum;
    
        destinationValue = a*sourceValue + b;
    
        return destinationValue;
    }
    
    float translateValueToPoint(float value, float xStart, float maximum, float width)
    {
        float point = (width * value) / maximum;
    //    
    //    point = xStart + point;
    //    
        return point;   
    }
    
    float translatePointToValue(float point, float xStart, float maximum, float width)
    {
        float value = (point) * maximum;
        value = value / width;
    
        return value;
    }
    
    
    CGFloat angleBetweenThreePoints(CGPoint centerPoint, CGPoint p1, CGPoint p2) {
        CGPoint v1 = CGPointMake(p1.x - centerPoint.x, p1.y - centerPoint.y);
        CGPoint v2 = CGPointMake(p2.x - centerPoint.x, p2.y - centerPoint.y);
    
        CGFloat angle = atan2f(v2.x*v1.y - v1.x*v2.y, v1.x*v2.x + v1.y*v2.y);
    
        return angle;
    }
    

    您还需要缩略图

    【讨论】:

      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 2011-05-22
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多