在 drawRect NSView(macOS 和 ObjC)之上绘制图像(作为叠加层)
Draw image (as an overlay) on top of drawRect NSView (macOS & ObjC)
我在 drawRect 上有一幅我很满意的绘图,我现在正尝试叠加来自特定路径的图像,我希望它作为叠加层继续在当前绘图之上。有谁知道最好的方法是什么,我希望能够设置这张图片的位置和大小。
这可以用核心图形来完成,还是我应该使用 NSImage 来完成这个 - 如果有人能指出正确的方向,我将不胜感激:)
您的 NSView
drawRect:
方法可以在 drawRect:
的子类实现之前或之后调用,这使您可以决定其他绘图代码是更早还是更晚执行,从而结束高于或低于 super
.
的绘图结果
// in subclass
- (void)drawRect:(CGRect)dirtyrect {
[super drawRect:dirtyrect]; //to draw super below
// ask for flip state first
CGFloat yFlip = self.flipped ? -1.0 : 1.0;
// your additional
// drawing code here..
// and do something with yFlip
// ...
//[super drawRect:dirtyrect]; //to draw super on top
}
由于在绘制时可能会考虑视图或图层的 flip
状态,因此您必须在进行自己的绘制调用之前检查翻转状态。为此,要求 self.flipped
或 super.flipped
以适应如上所示的视图翻转状态。
但是有很多不同的方法可以将翻转内容与非翻转内容混合使用。
以下代码通过使用 lockFocusFlipped:
方法而不是 lockFocus
方法锁定焦点来创建 NSImage
时遵循 self.flipped
状态。
还展示了其他 API,ps:您不必实现 imageRepresentation,以下包含或多或少的 pseudo 代码
- (NSImage *)imageRepresentation
{
//BOOL wasHidden = self.isHidden;
//CGFloat wantedLayer = self.wantsLayer;
//self.hidden = NO;
//self.wantsLayer = YES;
NSImage *image = [[NSImage alloc] initWithSize:self.bounds.size];
// to flip an image according to the views flip state
//[image lockFocus];
[image lockFocusFlipped:self.flipped];
CGContextRef ctx = [NSGraphicsContext currentContext].CGContext;
// to flip with CoreGraphics API
//CGContextScaleCTM(ctx, 1.0, -1.0); // <-- see -1.0?
//CGContextTranslateCTM(ctx, 1.0, 1.0);
// or Affine Transform API, pseudo code
//NSAffineTransform *trans = [NSAffineTransform transform];
//[trans translateXBy:0 yBy:existingSize.height];
//[trans scaleXBy:1 yBy:-1];
//[trans concat];
//[image drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositingOperationSourceOver fraction:1.0];
//[self.layer renderInContext:ctx]; // <-- CALayer backed view drawing
[self drawRect:self.bounds.size]; // <-- classic View drawing
[image unlockFocus];
//self.wantsLayer = wantedLayer;
//self.hidden = wasHidden;
return image;
}
我在 drawRect 上有一幅我很满意的绘图,我现在正尝试叠加来自特定路径的图像,我希望它作为叠加层继续在当前绘图之上。有谁知道最好的方法是什么,我希望能够设置这张图片的位置和大小。
这可以用核心图形来完成,还是我应该使用 NSImage 来完成这个 - 如果有人能指出正确的方向,我将不胜感激:)
您的 NSView
drawRect:
方法可以在 drawRect:
的子类实现之前或之后调用,这使您可以决定其他绘图代码是更早还是更晚执行,从而结束高于或低于 super
.
// in subclass
- (void)drawRect:(CGRect)dirtyrect {
[super drawRect:dirtyrect]; //to draw super below
// ask for flip state first
CGFloat yFlip = self.flipped ? -1.0 : 1.0;
// your additional
// drawing code here..
// and do something with yFlip
// ...
//[super drawRect:dirtyrect]; //to draw super on top
}
由于在绘制时可能会考虑视图或图层的 flip
状态,因此您必须在进行自己的绘制调用之前检查翻转状态。为此,要求 self.flipped
或 super.flipped
以适应如上所示的视图翻转状态。
但是有很多不同的方法可以将翻转内容与非翻转内容混合使用。
以下代码通过使用 lockFocusFlipped:
方法而不是 lockFocus
方法锁定焦点来创建 NSImage
时遵循 self.flipped
状态。
还展示了其他 API,ps:您不必实现 imageRepresentation,以下包含或多或少的 pseudo 代码
- (NSImage *)imageRepresentation
{
//BOOL wasHidden = self.isHidden;
//CGFloat wantedLayer = self.wantsLayer;
//self.hidden = NO;
//self.wantsLayer = YES;
NSImage *image = [[NSImage alloc] initWithSize:self.bounds.size];
// to flip an image according to the views flip state
//[image lockFocus];
[image lockFocusFlipped:self.flipped];
CGContextRef ctx = [NSGraphicsContext currentContext].CGContext;
// to flip with CoreGraphics API
//CGContextScaleCTM(ctx, 1.0, -1.0); // <-- see -1.0?
//CGContextTranslateCTM(ctx, 1.0, 1.0);
// or Affine Transform API, pseudo code
//NSAffineTransform *trans = [NSAffineTransform transform];
//[trans translateXBy:0 yBy:existingSize.height];
//[trans scaleXBy:1 yBy:-1];
//[trans concat];
//[image drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositingOperationSourceOver fraction:1.0];
//[self.layer renderInContext:ctx]; // <-- CALayer backed view drawing
[self drawRect:self.bounds.size]; // <-- classic View drawing
[image unlockFocus];
//self.wantsLayer = wantedLayer;
//self.hidden = wasHidden;
return image;
}