我从 CGGradient 复制了功能。编写此函数以从特定范围获取颜色。
// function: get color depending on min and max range for progress control
// param progress: current progress in progress range; eg. with range [-20, 60], progress can be any value in between
// param colors: array of float values representing color RGBA components in [0, 255] range
// param locationRange: array of float values representing amount of color for two colors
// param numElements: numer of colors and number of locations
// note: min and max range can be a combination of positive and negative values: [-20, 50], [0, 100], [30, 90], [-60, -30]
+ (UIColor*) colorForProgress:(CGFloat)progress lowerRange:(CGFloat)lowerRange upperRange:(CGFloat)upperRange colorRGBAArray:(CGFloat*)colors locationRange:(CGFloat*)locationRange numElements:(NSUInteger)numElements
{
NSAssert(colors != NULL, @"color array is NULL");
NSAssert(locationRange != NULL, @"numElements is NULL");
#ifdef DEBUG
for (int i = 0; i < numElements; i++)
{
NSAssert2(locationRange[i] >= 0.0f && locationRange[i] <= 1.0f, @"locationRange %d %6.2f not in range [0.0, 1.0]", i, locationRange[i]);
}
#endif
UIColor *resultColor;
// convert user range to local range
// normalize range to [0-n]
CGFloat rangeNormalized = upperRange - lowerRange;
NSLog(@"rangeNormalized: %6.2f", rangeNormalized);
// normalize input to range [0, range_normalized_max]
// r = progress - lowerRange
CGFloat progressNormalized = progress - lowerRange;
NSLog(@"progressNormalized: %6.2f", progressNormalized);
// map normalized range to [0, 100] percent
CGFloat progressPercent = (100.0f / rangeNormalized) * progressNormalized;
NSLog(@"progressPercent: %6.2f", progressPercent);
// map normalized progress to [0.0, 1.0]
CGFloat progressLocal = progressPercent / 100.0f;
NSLog(@"progress_01: %6.2f", progressLocal);
NSAssert(progressLocal >= 0.0f && progressLocal <= 1.0f, @"progress_01 not in range [0.0, 1.0]");
// find two colors for range_s
CGFloat b1 = 0, b2 = 0, *color1 = NULL, *color2 = NULL;
if (progressLocal < 1.0f)
{
for (int i = 0; i < numElements - 1; i++) // ingore last
{
if (progressLocal >= locationRange[i] && progressLocal < locationRange[i+1])
{
b1 = locationRange[i];
b2 = locationRange[i+1];
color1 = colors + (4 * i); // iterate colors
color2 = colors + (4 * (i+1));
break;
}
}
} else if (progressLocal == 1.0f)
{
b1 = locationRange[numElements - 2];
b2 = locationRange[numElements - 1];
color1 = colors + (4 * (numElements - 2));
color2 = colors + (4 * (numElements - 1));
}
NSLog(@"b1: %6.2f, b2: %6.2f", b1, b2);
NSLog(@"color1: %6.2f, %6.2f, %6.2f, %6.2f", color1[0], color1[1], color1[2], color1[3]);
NSLog(@"color2: %6.2f, %6.2f, %6.2f, %6.2f", color2[0], color2[1], color2[2], color2[3]);
CGFloat localRange = b2 - b1;
NSLog(@"localRange: %6.2f", localRange);
CGFloat localAmount = progressLocal - b1;
NSLog(@"localAmount: %6.2f", localAmount);
// colors
CGFloat newColors[4];
// each color component in both colors
for (int i = 0; i < 3; i++)
{
printf("\n");
NSLog(@"color1[%d]: %6.2f", i, color1[i]);
NSLog(@"color2[%d]: %6.2f", i, color2[i]);
newColors[i] = color1[i];
NSLog(@"newColors[%d]: %6.2f", i, newColors[i]);
CGFloat color_range = color1[i] > color2[i] ? (color1[i] - color2[i]) : (color2[i] - color1[i]);
NSLog(@"color_range: %6.2f", color_range);
// color_range map localRange
CGFloat incr = color_range / localRange;
NSLog(@"incr: %6.2f", incr);
CGFloat result = incr * localAmount;
if (color1[i] > color2[i])
{
result = -result;
}
NSLog(@"result: %6.2f", result);
newColors[i] += result;
NSLog(@"newColors[%d]: %6.2f", i, newColors[i]);
}
resultColor = [UIColor colorWithRed:newColors[0] / 255.0f green:newColors[1] / 255.0f blue:newColors[2] / 255.0f alpha:1.0f];
printUIColor(resultColor);
return resultColor;
}
如果有人提出更好的解决方案,我会暂时不回答这个问题。