Pregunta

AppKit is not available in iOS, so I was looking for a replacement.

Specifically, I was looking for a replacement method for:

- (NSColor *)interpolatedColorAtLocation: (CGFloat)location

I need a way to define a gradient, and lookup a colour value based on an input location (float).

¿Fue útil?

Solución

If you actually need a gradient object (for drawing the gradient?), you can use the CG-level CGGradient "class".

As for interpolating the color at a specific location in the gradient all you need to know are the two surrounding colors (relative to your given location) and the interpolate between them (t would then be a location between 0.0..1.0 relative to the two colors, not the entire gradient):

- (UIColor *)colorByInterpolatingWith:(UIColor *)color factor:(CGFloat)factor {
    factor = MIN(MAX(t, 0.0), 1.0);

    const CGFloat *startComponent = CGColorGetComponents(self.CGColor);
    const CGFloat *endComponent = CGColorGetComponents(color.CGColor);

    float startAlpha = CGColorGetAlpha(self.CGColor);
    float endAlpha = CGColorGetAlpha(color.CGColor);

    float r = startComponent[0] + (endComponent[0] - startComponent[0]) * factor;
    float g = startComponent[1] + (endComponent[1] - startComponent[1]) * factor;
    float b = startComponent[2] + (endComponent[2] - startComponent[2]) * factor;
    float a = startAlpha + (endAlpha - startAlpha) * factor;

    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

Example use:

UIColor *purpleColor = [[UIColor redColor] colorByInterpolatingWith:[UIColor blueColor] factor:0.5];

Otros consejos

Swift version (macOS)

This color interpolation can be achieved with the simple line:

let color = NSColor.green.interpolate(.blue, 0.5)

Add this extension to your project:

   extension NSColor{
    /**
     * Interpolates between two NSColors
     * EXAMPLE: NSColor.green.interpolate(.blue, 0.5)
     * NOTE: There is also a native alternative: NSColor.green.blended(withFraction: 0.5, of: .blue)
     */
    func interpolate(_ to:NSColor,_ scalar:CGFloat)->NSColor{
        func interpolate(_ start:CGFloat,_ end:CGFloat,_ scalar:CGFloat)->CGFloat{
            return start + (end - start) * scalar
        }
        let fromRGBColor:NSColor = self.usingColorSpace(.genericRGB)!
        let toRGBColor:NSColor = to.usingColorSpace(.genericRGB)!
        let red:CGFloat = interpolate(fromRGBColor.redComponent, toRGBColor.redComponent,scalar)
        let green:CGFloat = interpolate(fromRGBColor.greenComponent, toRGBColor.greenComponent,scalar)
        let blue:CGFloat = interpolate(fromRGBColor.blueComponent, toRGBColor.blueComponent,scalar)
        let alpha:CGFloat = interpolate(fromRGBColor.alphaComponent, toRGBColor.alphaComponent,scalar)
        return NSColor.init(red: red, green: green, blue: blue, alpha: alpha)
    }
}

The bellow animation was achived with this extension and AnimLib

enter image description here

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top