- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在实现一个自定义 NSMenuItem View shows a highlight当用户将鼠标悬停在其上时。为此,代码在将 [NSColor selectedMenuItemColor]
设置为事件颜色后调用 NSRectFill
。不过,我注意到结果不仅仅是简单的纯色 - 它实际上绘制了渐变。非常好,但想知道这个“魔法”是如何工作的 - 也就是说,如果我想定义自己的颜色,而不仅仅是绘制实体,我会怎么做?
最佳答案
我不知道这实际上是如何工作的,但我找到了一种使用自定义渐变(或任何其他绘图操作)复制行为的方法。 “技巧”是使用 CGPatternRef,它允许您指定用于绘制图案的回调函数。通常,此回调函数会绘制图案的一个“单元格”,但您可以指定一个非常大的图案大小(例如 CGFLOAT_MAX
),以便能够在一次回调调用中填充整个区域。
为了演示该技术,这里有一个 NSColor
上的类别,允许您从 NSGradient
创建颜色。当您设置
该颜色,然后使用它填充一个区域时,就会绘制渐变(线性,从下到上,但您可以轻松更改)。这甚至适用于描边路径或填充非矩形路径,例如 [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(0, 0, 100, 100)] fill]
因为 NSBezierPath
自动剪辑绘图。
//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];
结果:
关于cocoa - +[NSColor selectedMenuItemColor] 如何神奇地绘制渐变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15643303/
我正在实现一个自定义 NSMenuItem View shows a highlight当用户将鼠标悬停在其上时。为此,代码在将 [NSColor selectedMenuItemColor] 设置为
我编写了自己的类似 NSMenu 的类,以在无边框 NSWindow 中的 NSSearchField 下方显示动态搜索结果。它运行良好,但如果我在 subview 的顶部添加一些填充,则无法正确绘制
我是一名优秀的程序员,十分优秀!