使用Core Graphics在Objective-C (iOS)中绘制角度/锥形/弧形渐变

4
我正在尝试使用Objective-C(IOS)绘制“圆锥形”/“弧形”渐变(我不知道正确的术语是什么)。就像以下thread中显示的图像一样,Photoshop将其称为“角度”渐变。
经过数天的搜索和查找互联网而毫无结果后,我决定在这里寻求帮助。我想做的是创建一个自定义UIView,它是一个圆形进度条,基本上是一个环,类似于TweetBot iPhone应用程序中看到的活动指示器(当您拖动刷新时显示,可以在视频here中看到,在iPhone屏幕顶部的17-18秒左右)。我希望进度指示器(环的填充)是一个简单的两种颜色的渐变,可以通过编程方式设置,并且视图可以调整大小。
我卡在了如何用渐变填充环形的问题上。通过谷歌搜索、阅读苹果的核心图形文档以及在SO上搜索,得到的答案要么是关于径向渐变,要么是关于线性/轴向渐变,这不是我想要实现的效果。
上面链接的帖子建议使用预制图像,但这不是一个选项,因为渐变的颜色应该是可设置的,视图应该是可调整大小的,进度条的填充显然并不总是100%满的(这将是上面帖子中所示渐变的状态)。
我唯一想到的解决方案是手动绘制渐变,而不是使用CGGradientRef,在圆形路径内剪切小片段的渐变,并用单色填充。虽然我不知道当进度条被动画时,这种方法的表现如何,它不应该很差,但可能会成为一个问题。
所以我的第一个问题是: 在Objective-C(IOS)中,是否有更简单/不同的解决方案来绘制锥形/弧形渐变,而不是我想出的解决方案? 第二个问题:
如果我必须使用我想出的解决方案手动在视图中绘制渐变,我如何确定或计算(如果可能的话)我正在尝试绘制的每个颜色“片段”(以图像下方所示)的值(HEX或RGBA)。

(无法链接图片){{link1:渐变分割插图}}


将渐变分割成纯色填充会导致性能非常糟糕,特别是在动画期间。我仍然记得,在我们用CGShading(这些是线性渐变)替换该方法后,有用户连续几天进入Adium IRC频道,每个人都感谢我们大大改善了性能。 - Peter Hosey
看看这个控件 - https://github.com/maxkonovalov/MKRingProgressView。它似乎与所需的结果相似。它使用动态生成的渐变来填充进度环。 - maxkonovalov
3个回答

4

看起来需要使用像素着色器进行处理。我记得在Quartz Composer中有一个示例可以模拟雷达扫描,并且使用像素着色器来产生和你描述的效果类似的效果。

编辑:

找到了。这个着色器是由Peter Graffignino编写的:

kernel vec4 radarSweep(sampler image, __color color1,__color color2, float angle, vec4 rect)
{
    vec4 val = sample(image, samplerCoord(image));
    vec2 locCart = destCoord();
    float theta, r, frac, angleDist;

    locCart.x = (locCart.x - rect.z/2.0) / (rect.z/2.0);
    locCart.y = (locCart.y - rect.w/2.0) / (rect.w/2.0);
    // locCart is now normalized
    theta = degrees(atan(locCart.y, locCart.x));
    theta = (theta < 0.0) ? theta + 360.0 : theta;
    r = length(locCart);
    angleDist = theta - angle;
    angleDist = (angleDist < 0.0) ? angleDist + 360.0 : angleDist;
    frac = 1.0 - angleDist/360.0;
    // sum up 3 decaying phosphors with different time constants
    val = val*exp2(-frac/.005) + (val+.1)*exp2(-frac/.25)*color1 + val*exp2(-frac/.021)*color2;
    val = r > 1.0 ? vec4(0.0, 0.0,0.0,0.0) : val; // constrain to circle
    return val;
}

遗憾的是,Quartz Composer不适用于IOS应用程序,因此这不是一个选择。 - Mordack
2
@Mordack - Quartz Composer只是这个OpenGL着色器的演示平台,并且不是必需的运行。它只是一种很好的快速原型方式,适用于这样的着色器。您应该能够实现一个OpenGL ES 2.0着色器来完成这个任务,尽管这并不容易。Peter的方法可能是我更喜欢的方法。 - Brad Larson
QC不可用,但像素着色器是可用的。使用QC尝试您的着色器代码。 - NSResponder
1
有没有关于如何在Cocoa中使用它的想法?特别是drawRect:? - Aditya Vaidyam

3
上面链接的帖子建议使用预制图像,但这不是一个选项,因为渐变的颜色应该是可设置的,视图应该是可调整大小的,进度条的填充显然并不总是100%满(这将是在上面的帖子中显示的渐变状态)。
没问题!
使用另一个问题中的非常黑到白的图像(或者如果需要更大的版本),如下所示:
1.剪辑到您想要绘制渐变的任何形状。 2.用渐变结束时的颜色填充。 3.使用黑白渐变图像作为掩模。 4.用渐变开始时的颜色填充。
您可以通过旋转掩模图像来旋转渐变。
这仅支持具有每个极端端点处颜色的最简单情况;它不能扩展到三个或更多颜色,并且不支持不寻常的渐变停止位置。

按照这个答案,解决了我在这里尝试做的事情,谢谢! - Mordack

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接