美文网首页IOS OC UI相关
iOS上基于HSB颜色模型的取色盘

iOS上基于HSB颜色模型的取色盘

作者: 蹦擦擦我勒个去 | 来源:发表于2018-11-06 23:20 被阅读0次

    取色器的实现

    1.取色器需要达到的效果:

    a.画出取色盘图:

    取色盘

    b.获取触摸位置的颜色;

    c.传入颜色时可以定位到相应的位置。

    2.需要用到的知识

    a.CGContext绘图;

    CGContextRef context = UIGraphicsGetCurrentContext(); // 获取图形上下文 CGContextSaveGState(context); //压栈当前的绘制状态CGContextAddEllipseInRect(context, CGRectMake(0, 0, size.width, size.height));//画一椭圆(这里是画圆)

    CGContextClip(context); //以后绘制动作都会被限定在那个区域中

    CGContextRestoreGState(context); //堆栈顶部的状态弹出,返回到之前的图形状态

    CGMutablePathRef path = CGPathCreateMutable();//创建路径

    CGPathMoveToPoint(path, 0, start.x, start.y);// 移动到起点

    CGPathAddLineToPoint(path, 0, end1.x, end1.y); //从起点画到终点的直线

    CGGradientRef gradient = CGGradientCreateWithColors(rgbColorSpace, (__bridge CFArrayRef)colors, NULL);// 创建渐变色

    CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation);//在当前Context中填充渐变色

    // 创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示   CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

    b.三角函数

    (1)角度与弧度转换

    1°=π/180°,1rad=180°/π。

    在数学和物理中,弧度是角的度量单位。它是由 国际单位制导出的单位,单位缩写是rad。定义:弧长等于半径的弧,其所对的圆心角为1弧度。

    atan2f(y,x)获取反正切值,若要用度表示反正切值,请将结果再乘以 180/π。

    如果返回的值<0,加上360。

    atan2f(x,y)*180/π - 90 就是逆时针对应的角度。

    3.画取色盘的思路

    圆心坐标center(x,y),半径r,圆周角度360度,HSB模型中B取值1。

    a.由效果图及HSB模型可知红色的度数为0,角度按顺时针颜色均匀分布

    b.由效果图及HSB模型可知取色盘从圆心到圆周颜色是渐变填充的,圆心的白色,圆周上是S取值1其角度对应的颜色:

    UIColor *color = [UIColor colorWithHue:i/(float)numberOfSegments saturation:1 brightness:1 alpha:1];

    c.将圆按角度等分成n份,画扇形,然后将每一个扇形进行渐变填充。

    4.相关计算

    a.通过点击的点计算h,s

    CGPoint center = CGPointMake(floorf(self.bounds.size.width/2.0f), floorf(self.bounds.size.height/2.0f));

    CGFloat radius = floorf(self.bounds.size.width/2.0f);   

    CGFloat dx = point.x - center.x;    

    CGFloat dy = point.y - center.y;

    CGFloat touchRadius = sqrtf(powf(dx, 2)+powf(dy, 2)); 

    if (touchRadius > radius) {        

        _saturation = 1.f;

    }    else {        

    _saturation = touchRadius / radius;  

      }         

    CGFloat angleRad = atan2f(dy, dx);  

    CGFloat angleDeg = angleRad * (180.0f/M_PI);  

      if (angleDeg < 0.f) {       

        angleDeg += 360.f;  

      }    

    _hue = angleDeg / 360.0f;

    b.通过h,s计算位置

        CGPoint center = CGPointMake(floorf(self.bounds.size.width / 2.f), floorf(self.bounds.size.height / 2.f));

        CGFloat radius = floorf(self.bounds.size.width/2.f);

    CGFloat angle =2*M_PI* _hue;

        CGFloat saturationRadius = radius *_saturation;

        CGPointpoint =CGPointMake(center.x+ saturationRadius *cosf(angle), center.y+ saturationRadius *sinf(angle));

    _bubbleLayer.position=CGPointMake(point.x, point.y);

        _bubbleLayer.fillColor = [UIColor colorWithHue:_hue saturation:_saturation brightness:1 alpha:1].CGColor;

    c.画圆

    CGPointcenter =CGPointMake(floorf(size.width/2.0f),floorf(size.height/2.0f));

        CGFloat radius = floorf(size.width/2.0f);        

        // 创建RGB色彩空间,创建这个以后,context里面用的颜色都是用RGB表示

        CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

        CGContextSaveGState(context);

        CGContextAddEllipseInRect(context, CGRectMake(0, 0, size.width, size.height));

        CGContextClip(context);

        NSInteger numberOfSegments =360;

        for(CGFloati =0; i < numberOfSegments; i++) {

            UIColor*color = [UIColorcolorWithHue:i/(float)numberOfSegmentssaturation:1brightness:1alpha:1];

            CGContextSetStrokeColorWithColor(context, color.CGColor);

            CGFloatsegmentAngle =2*M_PI/ (float)numberOfSegments;

            CGPointstart = center;

            CGPointend =CGPointMake(center.x+ radius *cosf(i * segmentAngle), center.y+ radius *sinf(i * segmentAngle));

            CGMutablePathRef path = CGPathCreateMutable();

            CGPathMoveToPoint(path,0, start.x, start.y);

            CGFloatoffsetFromMid =2.f*(M_PI/180);

            CGPointend1 =CGPointMake(center.x+ radius *cosf(i * segmentAngle-offsetFromMid), center.y+ radius *sinf(i * segmentAngle-offsetFromMid));

            CGPointend2 =CGPointMake(center.x+ radius *cosf(i * segmentAngle+offsetFromMid), center.y+ radius *sinf(i * segmentAngle+offsetFromMid));

            CGPathAddLineToPoint(path,0, end1.x, end1.y);

            CGPathAddLineToPoint(path,0, end2.x, end2.y);

            CGContextSaveGState(context);

            CGContextAddPath(context, path);

            CGPathRelease(path);

            CGContextClip(context);

            NSArray*colors =@[(__bridgeid)[UIColorcolorWithWhite:1alpha:1].CGColor, (__bridgeid)color.CGColor];

            // 通过成对的颜色值(colors)和位置(locations)创建一个渐变色,colors是一个由CGColor对象组成的非空数组,如果space非空,所有颜色都会转换到该色彩空间,并且渐变将绘制在这个色彩空间里面;否则(space为NULL),每一种颜色将会被转换并且绘制在一般的RGB色彩空间中。如果locations为NULL,第一个颜色在location 0,最后一个颜色在location 1, 并且中间的颜色将会等距分布在中间。locations中的每一个location应该是一个0~1之间的CGFloat值;locations数字的元素数量应该跟colors中的一样,如果没有颜色提供给0或者1,这个渐变将使用location中最靠近0或者1的颜色值

            CGGradientRefgradient =CGGradientCreateWithColors(rgbColorSpace, (__bridgeCFArrayRef)colors,NULL);

            // 在当前context的裁剪的区域中,填充一个从startPoint到endPoint的线性渐变颜色。渐变色中location 0对应着startPoint;location 1对应着endPoint;颜色将根据locations的值线性插入在这两点(startPoint,endPoint)之间。option标志控制在startPoint之前和endPoint之后时候填充颜色。(跟开始的颜色还有最后的颜色相同)

            CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation);

            CGGradientRelease(gradient);

            CGContextRestoreGState(context);

        }

        CGColorSpaceRelease(rgbColorSpace);

        CGContextRestoreGState(context);

        CGContextSetStrokeColorWithColor(context, UIColor.clearColor.CGColor);

        CGContextSetLineWidth(context, 1);

        CGContextStrokeEllipseInRect(context, CGRectMake(0, 0, size.width, size.height));

    5.调整

    通过这样出来的效果是达到了,但是和效果图时相反的,解决方法

    a.画圆的时候:将颜色取角度对应相反的

     UIColor*color = [UIColorcolorWithHue:1-i/(float)numberOfSegmentssaturation:1brightness:1alpha:1];

    b.通过h,s计算位置

    CGFloat angle =2*M_PI*(1- _hue);

    c.通过点击的点计算h,s

        CGFloatangleRad =atan2f(dx, dy);

        CGFloatangleDeg = (angleRad * (180.0f/M_PI) -90);

    相关文章

      网友评论

        本文标题:iOS上基于HSB颜色模型的取色盘

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