Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 量规的岩芯图形角度梯度_Ios_Core Graphics_Gradient_Angle_Gauge - Fatal编程技术网

Ios 量规的岩芯图形角度梯度

Ios 量规的岩芯图形角度梯度,ios,core-graphics,gradient,angle,gauge,Ios,Core Graphics,Gradient,Angle,Gauge,我正在尝试将角度渐变应用于使用我在自定义UIView类中编写的代码创建的虚线,如下所示。虽然它需要调整,但我对它迄今为止产生的结果感到满意 鉴于视图初始化(如下)中的输入参数,以及iPad Air2在纵向模式下的768*768帧,它会生成以下仪表: 我想做的是使每个破折号通过一个用户定义的渐变,例如从绿色到红色,很像这样(在Photoshop中被拼凑): 我到处寻找,却找不到任何可以实现这一目标的东西。唯一接近的东西是使用不同的绘图方法,我想保持我的绘图程序 就我而言,我应该能够打电话: C

我正在尝试将角度渐变应用于使用我在自定义UIView类中编写的代码创建的虚线,如下所示。虽然它需要调整,但我对它迄今为止产生的结果感到满意

鉴于视图初始化(如下)中的输入参数,以及iPad Air2在纵向模式下的768*768帧,它会生成以下仪表:

我想做的是使每个破折号通过一个用户定义的渐变,例如从绿色到红色,很像这样(在Photoshop中被拼凑):

我到处寻找,却找不到任何可以实现这一目标的东西。唯一接近的东西是使用不同的绘图方法,我想保持我的绘图程序

就我而言,我应该能够打电话:

CGContextSetStrokeColorWithColor(myContext,[渐变颜色在此显示])

在绘制循环中,就是这样,但我不知道如何创建相关的颜色数组/渐变,并根据索引将线条绘制颜色更改为该数组

任何帮助都将不胜感激

- (void)drawRect:(CGRect)rect {

    myContext = UIGraphicsGetCurrentContext();
    UIImage *gaugeImage = [self radials:300 andSteps:3 andLineWidth:10.0];
    UIImageView *gaugeImageView = [[UIImageView alloc] initWithImage:gaugeImage];
    [self addSubview:gaugeImageView];

}

-(UIImage *)radials:(NSInteger)degrees andSteps:(NSInteger)steps andLineWidth:(CGFloat)lineWidth{

    UIGraphicsBeginImageContext(self.bounds.size);
    myContext = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(myContext, lineWidth);
    CGContextSetStrokeColorWithColor(myContext, [[UIColor blackColor] CGColor]);

    CGPoint center = CGPointMake(self.bounds.origin.x+(self.bounds.size.width/2), self.bounds.origin.y+(self.bounds.size.height/2));
    CGFloat r1 = center.x * 0.87f;
    CGFloat r2 = center.x * 0.95f;

    CGContextTranslateCTM(myContext, center.x, center.y);
    CGContextBeginPath(myContext);

    CGFloat offset  = 0;

    if(degrees < 360){
        offset = (360-degrees) / 2;
    }

    for(int lp = offset + 0 ; lp < offset + degrees+1 ; lp+=steps){

        CGFloat theta = lp * (2 * M_PI / 360);
        CGContextMoveToPoint(myContext, 0, 0);

        r1 = center.x * 0.87f;
        if(lp % 10 == 0){
            r1 = center.x * 0.81f;
        }

        CGContextMoveToPoint(myContext, sin(theta) * r1, cos(theta) * r1);
        CGContextAddLineToPoint(myContext, sin(theta) * r2, cos(theta) * r2);
        CGContextStrokePath(myContext);
    }

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
-(void)drawRect:(CGRect)rect{
myContext=UIGraphicsGetCurrentContext();
UIImage*gaugeImage=[自半径:300,步长:3,线宽:10.0];
UIImageView*gaugeImageView=[[UIImageView alloc]initWithImage:gaugeImageView];
[自添加子视图:gaugeImageView];
}
-(UIImage*)半径:(NSInteger)度和步长:(NSInteger)步长和线宽:(CGFloat)线宽{
UIGraphicsBeginImageContext(self.bounds.size);
myContext=UIGraphicsGetCurrentContext();
CGContextSetLineWidth(myContext,lineWidth);
CGContextSetStrokeColorWithColor(myContext,[[UIColor blackColor]CGColor]);
CGPoint center=CGPointMake(self.bounds.origin.x+(self.bounds.size.width/2)、self.bounds.origin.y+(self.bounds.size.height/2));
cGR1=中心x*0.87f;
CGFloat r2=中心x*0.95f;
cgContextTranslateCm(myContext,center.x,center.y);
CGContextBeginPath(myContext);
CGFloat偏移=0;
如果(度<360度){
偏移=(360度)/2;
}
对于(int-lp=偏移+0;lp<偏移+度+1;lp+=步长){
CGFloatθ=lp*(2*MμPI/360);
CGContextMoveToPoint(myContext,0,0);
r1=中心x*0.87f;
如果(lp%10==0){
r1=中心x*0.81f;
}
CGContextMoveToPoint(myContext,sin(θ)*r1,cos(θ)*r1);
CGContextAddLineToPoint(myContext,sin(θ)*r2,cos(θ)*r2);
CGContextStrokePath(myContext);
}
UIImage*image=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsSendImageContext();
返回图像;
}
就我而言,我应该能够简单地调用CGContextSetStrokeColorWithColor

然而,现实对“就你而言”并不感兴趣。您正在描述一个角度渐变。事实上,没有内置的核心图形工具来创建角度渐变

但是,您可以使用一个好的库(例如)轻松地完成此操作。这是一个简单的问题,以绘制角度梯度,并使用您的规画作为遮罩

通过这种方式,我得到了这个-不是在Photoshop中乱涂乱画,而是在iOS中完全实时完成,使用AngleGradientLayer,再加上您的
radials:andSteps:andLineWidth:
方法刚刚复制粘贴并用于生成遮罩:

这是我唯一要写的代码。首先,生成角度渐变层:

+ (Class)layerClass {
    return [AngleGradientLayer class];
}
- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        AngleGradientLayer *l = (AngleGradientLayer *)self.layer;
        l.colors = [NSArray arrayWithObjects:
           (id)[UIColor colorWithRed:1 green:0 blue:0 alpha:1].CGColor,
           (id)[UIColor colorWithRed:0 green:1 blue:0 alpha:1].CGColor,
           nil];
        l.startAngle = M_PI/2.0;
    }
    return self;
}
第二,面具(这部分是Swift的,但不相关):


所以,你想要这样的东西:

首先,一些温和的建议:

  • 不要在
    drawRect:
    中添加子视图。如果第二次调用
    drawRect:
    ,例如,如果视图的大小发生变化,该怎么办

    下面是关于实现
    drawRect:
    的说明:

    drawRect:
    方法的实现应该只做一件事:绘制内容。此方法不适用于更新应用程序的数据结构或执行与绘图无关的任何任务。它应该配置绘图环境,绘制内容,并尽快退出。如果您的
    drawRect:
    方法可能会被频繁调用,那么您应该尽可能优化绘图代码,并在每次调用该方法时尽可能少地绘制

    如果需要添加或删除子视图,则应在初始化视图时或最迟在
    layoutSubviews
    中添加或删除子视图

  • 根本不需要绘制图像或使用图像视图。
    drawRect:
    的整个要点是绘制到当前图形上下文中,UIKit已经设置了当前图形上下文,以视图的备份存储为目标

  • 抛开这些建议不谈,核心图形中不支持角度梯度。但是,对于您的图形,您可以分别设置每个记号的颜色,并获得相当好的近似值,这就是我创建上面图像的方式。用于创建颜色,根据刻度角度计算色调参数

    如果将绘图代码分解为单独的类,则可以很容易地使用它直接绘制到视图(在
    drawRect:
    中),或者绘制到图像(如果需要)。以下是界面:

    @interface RainbowGaugeAppearance: NSObject
    
    @property (nonatomic) CGFloat startDegrees;
    @property (nonatomic) CGFloat endDegrees;
    @property (nonatomic) CGFloat degreesPerMajorTick;
    @property (nonatomic) int subdivisionsPerMajorTick;
    @property (nonatomic) CGFloat tickThickness;
    @property (nonatomic) CGFloat startHue;
    @property (nonatomic) CGFloat endHue;
    @property (nonatomic) CGFloat outerRadiusFraction;
    @property (nonatomic) CGFloat minorInnerRadiusFraction;
    @property (nonatomic) CGFloat majorInnerRadiusFraction;
    
    - (instancetype _Nonnull)init;
    - (void)drawInRect:(CGRect)rect;
    @end
    
    以及实施:

    @implementation RainbowGaugeAppearance
    
    static CGFloat radiansForDegrees(CGFloat degrees) { return degrees * M_PI / 180; }
    
    - (instancetype _Nonnull)init {
        if (self = [super init]) {
            _startDegrees = 120;
            _endDegrees = _startDegrees + 300;
            _degreesPerMajorTick = 30;
            _subdivisionsPerMajorTick = 10;
            _tickThickness = 4;
            _outerRadiusFraction = 0.95;
            _minorInnerRadiusFraction = 0.87;
            _majorInnerRadiusFraction = 0.81;
            _startHue = 1/ 3.0;
            _endHue = 0;
        }
        return self;
    }
    
    - (void)drawInRect:(CGRect)rect {
        CGContextRef gc = UIGraphicsGetCurrentContext();
        CGContextSaveGState(gc); {
            CGContextTranslateCTM(gc, CGRectGetMidX(rect), CGRectGetMidY(rect));
            CGContextSetLineWidth(gc, self.tickThickness);
            CGContextSetLineCap(gc, kCGLineCapButt);
    
            CGFloat outerRadius = _outerRadiusFraction / 2 * rect.size.width;
            CGFloat minorInnerRadius = _minorInnerRadiusFraction / 2 * rect.size.width;
            CGFloat majorInnerRadius = _majorInnerRadiusFraction / 2 * rect.size.width;
    
            CGFloat degreesPerTick = _degreesPerMajorTick / _subdivisionsPerMajorTick;
            for (int i = 0; ; ++i) {
                CGFloat degrees = _startDegrees + i * degreesPerTick;
                if (degrees > _endDegrees) { break; }
    
                CGFloat t = (degrees - _startDegrees) / (_endDegrees - _startDegrees);
                CGFloat hue = _startHue + t * (_endHue - _startHue);
                CGContextSetStrokeColorWithColor(gc, [UIColor colorWithHue:hue saturation:0.8 brightness:1 alpha:1].CGColor);
    
                CGFloat sine = sin(radiansForDegrees(degrees));
                CGFloat cosine = cos(radiansForDegrees(degrees));
                CGFloat innerRadius = (i % _subdivisionsPerMajorTick == 0) ? majorInnerRadius : minorInnerRadius;
                CGContextMoveToPoint(gc, outerRadius * cosine, outerRadius * sine);
                CGContextAddLineToPoint(gc, innerRadius * cosine, innerRadius * sine);
                CGContextStrokePath(gc);
            }
        } CGContextRestoreGState(gc);
    }
    
    @end
    
    使用它来绘制视图是很简单的:

    @implementation RainbowGaugeView {
        RainbowGaugeAppearance *_appearance;
    }
    
    - (RainbowGaugeAppearance *_Nonnull)appearance {
        if (_appearance == nil) { _appearance = [[RainbowGaugeAppearance alloc] init]; }
        return _appearance;
    }
    
    - (void)drawRect:(CGRect)rect {
        [self.appearance drawInRect:self.bounds];
    }
    
    @end
    

    不要这样误用
    drawRect
    drawRect
    用于绘图-不用于添加子视图。请记住,
    drawRect
    被多次调用,而您只需一次又一次地添加该子视图,这太荒谬了。这是正确的!我错了!杰出的所以说不要使用像“谢谢”这样的注释,但我不知道为什么,所以感谢您提供了一个简单的解决方案和经验教训。
    AngleGradientLayer
    的问题是它在RGB空间中插入了一条线性路径。这就是为什么这里的黄色和橙色看起来如此
    @implementation RainbowGaugeView {
        RainbowGaugeAppearance *_appearance;
    }
    
    - (RainbowGaugeAppearance *_Nonnull)appearance {
        if (_appearance == nil) { _appearance = [[RainbowGaugeAppearance alloc] init]; }
        return _appearance;
    }
    
    - (void)drawRect:(CGRect)rect {
        [self.appearance drawInRect:self.bounds];
    }
    
    @end