我想对一个NSView子类做几个简单的转换,把它翻转到X轴、Y轴或者两者兼而有之。我是一个经验丰富的iOS开发人员,但我不知道如何在macOS中实现这一点。我已经创建了一个具有所需翻译和缩放的NSAffineTransform,但无法确定如何将其实际应用于NSView。唯一可以接受任何类型转换的属性是[[NSView layer] transform],但这需要一个CATransform3D。
我唯一的成功是使用转换来翻转图像,如果是一个NSImageView,方法是在一个新的空NSImage上调用lockFocus,创建转换,然后在锁定的图像中绘制未翻转的图像。然而,这远不能令人满意,因为它不处理任何子视图,而且可能比直接将转换应用到NSView/NSImageView要花费更多。
发布于 2019-02-03 10:38:12
这就是解决办法:
- (void)setXScaleFactor:(CGFloat)xScaleFactor {
_xScaleFactor = xScaleFactor;
[self setNeedsDisplay];
}
- (void)setYScaleFactor:(CGFloat)yScaleFactor {
_yScaleFactor = yScaleFactor;
[self setNeedsDisplay];
}
- (void)drawRect:(NSRect)dirtyRect {
NSAffineTransform *transform = [[NSAffineTransform alloc] init];
[transform scaleXBy:self.xScaleFactor yBy:self.yScaleFactor];
[transform set];
[super drawRect:dirtyRect];
}感谢L‘l关于使用NSGraphicsContext的提示。
发布于 2022-11-20 16:24:36
我不敢相信,在我能够在AppKit中水平翻转图像之前,我需要做多少个小时的搜索和实验。我不能再提这个问题和捣蛋鬼的答案了。
这里是我的解决方案的更新版本,用于横向翻转图像。此方法在NSImageView子类中实现。
override func draw(_ dirtyRect: NSRect) {
// NSViews are not backed by CALayer by default in AppKit. Must request a layer
self.wantsLayer = true
if self.flippedHoriz {
// If a horizontal flip is desired, first multiple every X coordinate by -1. This flips the image, but does it around the origin (lower left), not the center
var trans = AffineTransform(scaledByX: -1, byY: 1)
// Add a transform that moves the image by the width so that its lower left is at the origin
trans.append(AffineTransform(translationByX: self.frame.size.width, byY: 0)
// AffineTransform is bridged to NSAffineTransform, but it seems only NSAffineTransform has the set() and concat() methods, so convert it and add the transform to the current graphics context
(trans as NSAffineTransform).concat()
}
// Don't be fooled by the Xcode placehoder. This must be *after* the above code
super.draw(dirtyRect)
}转换的行为也需要一些实验才能理解。NSAffineTransform.set()的帮助解释道:
it removes the existing transformation matrix, which is an accumulation of transformation matrices for the screen, window, and any superviews.这很可能会破坏一些东西。由于我仍然希望尊重由窗口和超级视图应用的所有转换,所以concat()方法更合适。
concat()将现有的转换矩阵乘以自定义转换。不过,这并不完全是累积的。每次调用draw时,都会将转换应用到视图的原始转换中。所以反复调用绘图不能连续翻转图像。因此,为了不翻转图像,只需不应用转换。
https://stackoverflow.com/questions/54501504
复制相似问题