Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.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
Iphone 使用石英二维/核心图形完成此绘图的最佳方法?_Iphone_Objective C_Quartz Graphics - Fatal编程技术网

Iphone 使用石英二维/核心图形完成此绘图的最佳方法?

Iphone 使用石英二维/核心图形完成此绘图的最佳方法?,iphone,objective-c,quartz-graphics,Iphone,Objective C,Quartz Graphics,作为我应用程序中一个视图的背景,我想在它的框架内画一个相当简单的矩形边框。这基本上是一个矩形渐变:在帧周围有一条黑线,在大约10-20像素的范围内逐渐变为白色。不幸的是,据我所知,Core Graphics不提供矩形渐变(使用CGGradient或CGShading)。所以我想知道最好的方法是什么 我想到两件事: 绘制一系列同心矩形,每个矩形的颜色都较浅,并在每侧插入1px。我想不出一个更简单的方法,但我必须自己做所有的梯度计算,可能需要很多图形操作 在线性模式下使用CGGradient,每侧一

作为我应用程序中一个视图的背景,我想在它的框架内画一个相当简单的矩形边框。这基本上是一个矩形渐变:在帧周围有一条黑线,在大约10-20像素的范围内逐渐变为白色。不幸的是,据我所知,Core Graphics不提供矩形渐变(使用
CGGradient
CGShading
)。所以我想知道最好的方法是什么

我想到两件事:

  • 绘制一系列同心矩形,每个矩形的颜色都较浅,并在每侧插入1px。我想不出一个更简单的方法,但我必须自己做所有的梯度计算,可能需要很多图形操作
  • 在线性模式下使用
    CGGradient
    ,每侧一次。但是为了让它工作,我想我需要先为每一侧设置一个梯形的剪裁区域,以便在拐角处斜接渐变
  • 似乎应该有一种方法可以使用路径笔划来实现这一点,但似乎没有一种方法可以定义两侧方向不同的图案。

    我选择选项2:

    在线性模式下使用CGGradient,每边一次。但是为了让它工作,我想我需要先为每一侧设置一个梯形的剪裁区域,以便在拐角处斜接渐变

    使用
    NSBezierPath
    创建梯形区域相当简单,只需执行四次绘图操作

    以下是创建左侧梯形区域的基本代码:

    NSRect outer = [self bounds];
    NSPoint outerPoint[4];
    outerPoint[0] = NSMakePoint(0, 0);
    outerPoint[1] = NSMakePoint(0, outer.size.height);
    outerPoint[2] = NSMakePoint(outer.size.width, outer.size.height);
    outerPoint[3] = NSMakePoint(outer.size.width, 0);
    
    NSRect inner = NSInsetRect([self bounds], borderSize, borderSize);
    NSPoint innerPoint[4];
    innerPoint[0] = inner.origin;
    innerPoint[1] = NSMakePoint(inner.origin.x,
                                inner.origin.y + inner.size.height);
    innerPoint[2] = NSMakePoint(inner.origin.x + inner.size.width,
                                inner.origin.y + inner.size.height);
    innerPoint[3] = NSMakePoint(inner.origin.x + inner.size.width,
                                inner.origin.y);
    
    NSBezierPath leftSidePath = [[NSBezierPath bezierPath] retain];
    [leftSidePath moveToPoint:outerPoint[0]];
    [leftSidePath lineToPoint:outerPoint[1]];
    [leftSidePath lineToPoint:innerPoint[1]];
    [leftSidePath lineToPoint:innerPoint[0]];
    [leftSidePath lineToPoint:outerPoint[0]];
    
    // ... etc.
    
    [leftSidePath release];
    

    像这样的事情也可以奏效。 基本上:不使用剪切路径,只需使用blendmode。 在这个例子中,梯度被缓存在CGLayer中

     CGContextRef ctx = UIGraphicsGetCurrentContext();
     CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
    
     CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
     CGContextFillRect(ctx,self.bounds);
    
     CGFloat w = self.bounds.size.width;
     CGFloat h = self.bounds.size.height;
     CGFloat dh = (w-h)/2;
    
     CGLayerRef l = CGLayerCreateWithContext(ctx,CGSizeMake(h,48.0f),NULL);
     CGContextRef lctx = CGLayerGetContext(l);
    
     float comp[] = { .2,.5,1.0,1.0,1.0,1.0,1.0,1.0};
     CGGradientRef gradient = CGGradientCreateWithColorComponents(cspace, comp, NULL, 2);
     CGContextDrawLinearGradient(lctx, gradient,CGPointMake(0,0),CGPointMake(0,48), 0);
    
     CGContextSaveGState(ctx);
     CGContextSetBlendMode(ctx,kCGBlendModeDarken);
     for(int n=1;n<5;n++)
     {
      CGContextTranslateCTM(ctx,w/2.0,h/2.0);
      CGContextRotateCTM(ctx, M_PI_2);
      CGContextTranslateCTM(ctx,-w/2.0,-h/2.0);
      CGContextDrawLayerAtPoint(ctx,CGPointMake((n%2)*dh,(n%2)*-dh),l);
     }
     CGContextRestoreGState(ctx);
    
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    CGColorSpaceRef cspace=CGColorSpaceCreateDeviceRGB();
    CGContextSetRGBFillColor(ctx,1.0,1.0,1.0,1.0);
    CGContextFillRect(ctx,self.bounds);
    CGFloat w=self.bounds.size.width;
    CGH=self.bounds.size.height;
    cgdh=(w-h)/2;
    CGLayerRef l=CGLayerCreateWithContext(ctx,CGSizeMake(h,48.0f),NULL);
    CGContextRef lctx=CGLayerGetContext(l);
    浮点comp[]={.2,5,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
    CGGradientRef gradient=CGGradientCreateWithColorComponents(cspace,comp,NULL,2);
    CGContextDrawLinearGradient(lctx,梯度,CGPointMake(0,0),CGPointMake(0,48),0);
    CGContextSaveGState(ctx);
    CGContextSetBlendMode(ctx、kCGBlendModeDarken);
    
    对于(int n=1;对每条边使用CGGradient会更快,但如果速度仍然太慢,可以使用UIImage作为缓存(绘制一次UIImage,然后在需要时将图像绘制到视图上)是的,我认为无论我采取什么方法绘制,缓存带有结果的图像可能都是一个好主意。但我有点喜欢按程序绘制,而不是在应用程序中发布PNG。作为一个(显然?)没有在iPhone(或Mac)上做过很多图形编程的人来说然而…有没有理由选择NSBezierPath?我看到的大多数示例都集中在核心图形API上。我在这里使用它是因为我以前使用过它,所以知道它是有效的。:)核心图形完全有可能做得更好。尝试一下也无妨,但一定要对代码进行分析,看看您是否获得了可衡量的性能提升(或者您是否真的需要这样做)。这与我最终得到的代码并不完全相同,但也很相似。没有比画四个梯形更好的解决方案了。