【问题标题】:Delaunay triangulation with gradient fill?带渐变填充的德劳内三角剖分?
【发布时间】:2013-06-12 21:49:42
【问题描述】:

我正在尝试重新创建类似这种形状的东西 - http://www.creativeapplications.net/wp-content/uploads/2010/09/horizon_02_1024x768.png - 在 iOS 上使用 UIKit 或 CoreGraphics。

图片中的那个是用 openFrameworks 完成的,它确实可以在 iOS 上运行。但是,我想在不使用 oF 的情况下构建相同的内容,因此我可以将其全部保留为原生。

我假设这个形状是通过 Delaunay 三角剖分创建的,我可以在 Objective-C 中完成。问题是用渐变而不是普通的 UIColor 填充形状!

有没有一种方法可以在 iPad 上以良好的性能在本地完成类似的事情,还是我应该使用 openFrameworks 来完成并将其作为层引入应用程序?

【问题讨论】:

  • 我不知道你为什么被投了几次票,所以这里是一个 +1 让你再次获得平衡。
  • 谢谢迈克尔,感激不尽;)

标签: objective-c ipad uikit


【解决方案1】:

您是在问如何用渐变填充三角形?下面的代码就是这样做的。要让它工作,你需要添加 QuartzCore 框架,并且

#import <QuartzCore/QuartzCore.h>

代码创建一个三角形的形状图层,然后将其用作渐变图层的蒙版。希望这会有所帮助。

- (void)drawRect:(CGRect)rect
{
    CGFloat w = self.bounds.size.width / 4;
    CGFloat h = self.bounds.size.height / 4;
    CGFloat x = w * 2;
    CGFloat y = h;
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path,NULL, x, y);
    CGPathAddLineToPoint(path, NULL, x+w, y+2*h);
    CGPathAddLineToPoint(path, NULL, x-w, y+2*h);
    CGPathCloseSubpath(path);


    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
    [shapeLayer setPath:path];

    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
    gradientLayer.startPoint = CGPointMake(0.25, 1.0);
    gradientLayer.endPoint = CGPointMake(0.75, 0.0);
    UIColor *startColour = [UIColor redColor];
    UIColor *endColour = [UIColor greenColor];
    gradientLayer.colors = [NSArray arrayWithObjects:(id)[startColour CGColor], (id)[endColour CGColor], nil];

    [gradientLayer setMask:shapeLayer];

    [self.layer addSublayer:gradientLayer];

    CGPathRelease(path);
}

【讨论】:

  • 嗨,迈克尔。我想知道如何用不同的渐变填充填充多个三角形,考虑到它们可能都共享一个视图/上下文
  • 这听起来是不是你需要一个渐变层数组,每个都是一个三角形,每个都有自己的蒙版?最困难的部分是找出哪个在哪个之上。
  • 如果这在相同的上下文中是可能的,那么这种分层方法可能就是我需要的!特别是因为它们永远不会重叠!会试一试
【解决方案2】:

我打算做一个三角形,但你可以使用重复来做多个:

//Create the triangle Path and clip the drawing to it
CGContextSaveGState(context);
CGContextBeginPath(context);
CGContextMoveToPoint(context, self.bounds.size.width * .4, self.bounds.size.height * 1/6.);
CGContextAddLineToPoint(context,self.bounds.size.width * .4, self.bounds.size.height * 3/6.);
CGContextAddLineToPoint(context,self.bounds.size.width * .2, self.bounds.size.height * 3/6.);
CGContextClosePath(context);
CGContextClip(context);

//Now call the linear gradient drawing function
[self drawLinearGradient:context withRect:self.bounds startColor:[UIColor colorWithRed:1 green:1 blue:1 alpha:.3] endColor:[UIColor colorWithRed:.5 green:.5 blue:.5 alpha:.3] startFraction:.3 stopFraction:1];

//And now restore so that we can clip the next triangle
CGContextRestoreGState(context);

现在是线性渐变绘制代码:

- (void) drawLinearGradient: (CGContextRef) context withRect: (CGRect) rect startColor: (UIColor*) startColor endColor: (UIColor*)  endColor startFraction:(float)start stopFraction:(float)stop
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGFloat locations[] = { start, stop };

    CGGradientRef myGradient;
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();

    CGColorRef startColorRef = [startColor CGColor];
    CGColorRef endColorRef = [endColor CGColor];

    const CGFloat *components = CGColorGetComponents(startColorRef);
    CGFloat red     = components[0];
    CGFloat green = components[1];
    CGFloat blue   = components[2];
    CGFloat alpha = components[3];

    const CGFloat *components2 = CGColorGetComponents(endColorRef);
    CGFloat red2     = components2[0];
    CGFloat green2 = components2[1];
    CGFloat blue2   = components2[2];
    CGFloat alpha2 = components2[3];

    CGFloat colors[] =
    {
        red, green, blue, alpha,
        red2, green2, blue2, alpha2
    };

    myGradient = CGGradientCreateWithColorComponents(rgb, colors, locations, 2);
    CGColorSpaceRelease(rgb);

    CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
    CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

    CGContextSaveGState(context);
    CGContextAddRect(context, rect);
    CGContextClip(context);
    CGContextDrawLinearGradient(context, myGradient, startPoint, endPoint, 0);
    CGContextRestoreGState(context);

    CGGradientRelease(myGradient);
    CGColorSpaceRelease(colorSpace);
}

如果您愿意,您可以设置此线性渐变函数来处理两个以上的位置/颜色。这是非常基本的,但是如果您知道每个三角形的开始和停止颜色以及位置,您应该能够使用此代码(无需数百个子层)完成您想要的(本机绘图)。虽然图层可能绘制得更快,但我不知道。

【讨论】:

  • 谢谢普茨。会试一试的!
猜你喜欢
  • 2012-04-27
  • 2020-05-12
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2022-01-09
  • 2013-11-18
  • 2014-03-24
相关资源
最近更新 更多