Darker border around the circular CALayer

I am creating a custom view to display one color, this is to pick a color from an image so that the color can change quite quickly. To prevent the color from shifting when moving the cursor, I made the color change animate for more than 0.2 seconds.

I am doing this with CALayer. However, it currently works almost as intended, however I want a slightly darker content color around the layer, similar to OS X Yosemite closing and resizing the window.

Circle with dark outline

The method I'm currently using works, however sometimes the border color animation doesn't seem to match the main color animation, sometimes it goes through lighter colors. I thought I could do it with filters, but I'm absolutely obsessed with how to do it, I couldn't find much documentation on the internet. I have very little experience with CoreAnimation, so I'm not sure if this is the best way to do it, or if it's blindingly obvious.

- (id)initWithFrame:(NSRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        _pickerColour = [NSColor whiteColor];
        strokeColour = [NSColor whiteColor];

        [self setWantsLayer: true];

        innerLayer = [CALayer layer];
        [innerLayer setCornerRadius: frame.size.width / 2];
        [innerLayer setBorderWidth: 4];
        [innerLayer setFrame: CGRectMake(frame.origin.x - frame.size.width / 2, frame.origin.y - frame.size.width / 2, frame.size.width - 2, frame.size.height - 2)];

        [self.layer addSublayer:innerLayer];
    }

    return self;
}

- (void) setPickerColour:(NSColor *)pickerColour{
    CABasicAnimation *backgroundAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    backgroundAnimation.fillMode = kCAFillModeForwards;
    backgroundAnimation.removedOnCompletion = NO;
    backgroundAnimation.fromValue = (id)self.pickerColour.CGColor;
    backgroundAnimation.toValue = (id)pickerColour.CGColor;
    backgroundAnimation.duration = 0.1f;
    [innerLayer addAnimation:backgroundAnimation forKey:@"backgroundColor"];

    CGFloat h,s,b,a;
    [[self.pickerColour colorUsingColorSpaceName: NSCalibratedRGBColorSpace] getHue:&h saturation:&s brightness:&b alpha:&a];
    NSColor *newStrokeColour = [NSColor colorWithHue:h saturation:MIN(s, 1.0) brightness: MAX(b / 1.2, 0.0) alpha:a];

    CABasicAnimation *borderAnimation = [CABasicAnimation animationWithKeyPath:@"borderColor"];
    borderAnimation.fillMode = kCAFillModeForwards;
    borderAnimation.removedOnCompletion = NO;
    borderAnimation.fromValue = (id)strokeColour.CGColor;
    borderAnimation.toValue = (id)newStrokeColour.CGColor;
    borderAnimation.duration = 0.1f;
    [innerLayer addAnimation:borderAnimation forKey:@"borderColor"];

    strokeColour = newStrokeColour;
    _pickerColour = pickerColour;
}

- (NSColor *) pickerColour{
    return _pickerColour;
}

      

+3


source to share


1 answer


By using CAKeyframeAnimation

instead CABasicAnimation

, you can provide arrays of values

and keyTimes

that contain a piecewise representation of your path through the color space. You can use the same convenience method NSColor

you are using, but you specify enough colors to follow the desired arc in HSV space instead of the default linear path through RGB space.



+2


source







All Articles