+[NSColor selectedMenuItemColor] 如何神奇地绘制渐变?

编程入门 行业动态 更新时间:2024-10-27 02:18:12
本文介绍了+[NSColor selectedMenuItemColor] 如何神奇地绘制渐变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

我正在实施一个自定义 NSMenuItem 视图,该视图显示亮点 当用户将鼠标悬停在它上面时.为此,代码在将 [NSColor selectedMenuItemColor] 设置为活动颜色后调用 NSRectFill.但是,我注意到结果只是一个纯色——它实际上绘制了一个渐变.非常好,但想知道这种魔法"是如何工作的——也就是说,如果我想定义自己的颜色,而不仅仅是绘制纯色,我该怎么做?

I'm implementing a custom NSMenuItem view that shows a highlight as the user mouses over it. To do this, the code calls NSRectFill after setting [NSColor selectedMenuItemColor] as the active color. However, I noticed that the result is not simply a solid color — it actually draws a gradient instead. Very nice, but wondering how this "magic" works — i.e. if I wanted to define my own color that didn't just draw solid, how would I?

推荐答案

我不知道这实际上是如何工作的,但我找到了一种使用自定义渐变(或任何其他绘图操作).技巧"是使用 CGPatternRef,它允许您指定用于绘制图案的回调函数.通常,此回调函数绘制模式的一个单元格",但您可以只指定一个非常大的模式大小(例如 CGFLOAT_MAX),以便能够在一次回调调用中填充整个区域.

I don't know how this actually works, but I found a way to replicate the behavior with custom gradients (or any other drawing operations). The "trick" is to use a CGPatternRef, which allows you to specify a callback function for drawing the pattern. Normally, this callback function draws one "cell" of the pattern, but you can just specify a very large pattern size (e.g. CGFLOAT_MAX) to be able to fill the entire area in one invocation of the callback.

为了演示该技术,这里是 NSColor 上的一个类别,它允许您从 NSGradient 创建颜色.当你设置那个颜色然后用它来填充一个区域时,渐变被绘制(线性,从下到上,但你可以很容易地改变它).这甚至适用于描边路径或填充非矩形路径,例如 [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(0, 0, 100, 100)] fill] 因为 NSBezierPath 自动剪辑绘图.

To demonstrate the technique, here's a category on NSColor that allows you to create a color from an NSGradient. When you set that color and then use it to fill an area, the gradient is drawn (linear, from bottom to top, but you can easily change that). This even works for stroking paths or filling non-rectangular paths, like [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(0, 0, 100, 100)] fill] because NSBezierPath automatically clips the drawing.

//NSColor+Gradient.h
#import <Cocoa/Cocoa.h>

@interface NSColor (Gradient)

+ (NSColor *)my_gradientColorWithGradient:(NSGradient *)gradient;

@end

//NSColor+Gradient.m
#import "NSColor+Gradient.h"
#import <objc/runtime.h>

static void DrawGradientPattern(void * info, CGContextRef context)
{
    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
    CGRect clipRect = CGContextGetClipBoundingBox(context);
    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];
    NSGradient *gradient = (__bridge NSGradient *)info;
    [gradient drawInRect:NSRectFromCGRect(clipRect) angle:90.0];
    [NSGraphicsContext setCurrentContext:currentContext];
}

@implementation NSColor (Gradient)

+ (NSColor *)my_gradientColorWithGradient:(NSGradient *)gradient
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern(NULL);
    CGPatternCallbacks callbacks;
    callbacks.drawPattern = &DrawGradientPattern;
    callbacks.releaseInfo = NULL;
    CGPatternRef pattern = CGPatternCreate((__bridge void *)(gradient), CGRectMake(0, 0, CGFLOAT_MAX, CGFLOAT_MAX), CGAffineTransformIdentity, CGFLOAT_MAX, CGFLOAT_MAX, kCGPatternTilingConstantSpacing, true, &callbacks);
    const CGFloat components[4] = {1.0, 1.0, 1.0, 1.0};
    CGColorRef cgColor = CGColorCreateWithPattern(colorSpace, pattern, components); 
    CGColorSpaceRelease(colorSpace);
    NSColor *color = [NSColor colorWithCGColor:cgColor];
    objc_setAssociatedObject(color, "gradient", gradient, OBJC_ASSOCIATION_RETAIN);
    return color;
}

@end

使用示例:

NSArray *colors = @[ [NSColor redColor], [NSColor blueColor] ];
NSGradient *gradient = [[NSGradient alloc] initWithColors:colors];
NSColor *gradientColor = [NSColor my_gradientColorWithGradient:gradient];
[gradientColor set];
NSRectFill(NSMakeRect(0, 0, 100, 100));
[[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(100, 0, 100, 100)] fill];

结果:

这篇关于+[NSColor selectedMenuItemColor] 如何神奇地绘制渐变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

更多推荐

[db:关键词]

本文发布于:2023-04-17 18:12:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/919140.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:神奇   NSColor   selectedMenuItemColor

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!