Mac OS X Cocoa, Flipping Y Coordinate in Global Screen Coordinate Space
How do I flip the y value of an NSPoint to a flipped coordinate space.
I have two sources of points, both in global screen space, but one is flipped:
one from a screen coordinate space with 0,0 = top left.
one from a screen coordinate space with 0,0 = bottom left.
I need to flip the second one (bottom开发者_运维问答 left) to be in the same space as the first one, top left. How can I do that on an NSPoint or CGPoint?
For Mac OSX Cocoa, you can flip the y
Coordinate for a view, just override isFlipped
to return YES
for each view:
- (BOOL)isFlipped {
return YES;
}
If you have multiple monitors, the overall height of the global coordinate space may be larger than the vertical height on any individual display. I found it necessary to use the following code (given originalPoint
) to find that:
let globalHeight = screens.map {$0.frame.origin.y + $0.frame.height}.max()!
let flippedY = globalHeight - originalPoint.y
let convertedPoint = NSPoint(x: originalPoint.x, y: flippedY)
Let's say you have a point in a bottom left coordinate space, called 'originalPoint'. To flip this point to a top left coordinate space, you can use the following code:
let screenFrame = (NSScreen.main()?.frame)!
let flippedY = screenFrame.size.height - originalPoint.y
let convertedPoint = NSPoint(x: originalPoint.x, y: flippedY)
We can also make an extension:
extension NSPoint {
var flipped: NSPoint {
let screenFrame = (NSScreen.main()?.frame)!
let screenY = screenFrame.size.height - self.y
return NSPoint(x: self.x, y: screenY)
}
}
Use:
let flippedPoint = originalPoint.flipped
I think the other answers are not quite correct and will fail in some circumstances.
See this post for what I think is the correct answer.
Here's my implementation for copy-pasting:
#pragma mark - Coordinate conversion
/// The *cocoa* global "display" coordinate system starts at the bottom left of the zero screen, while the *quartz* coordinate system starts at the top left
/// We sometimes need to convert between them
/// Convenience wrappers
+ (CGPoint)flipPoint:(CGPoint)point {
return [self cocoaToQuartzScreenSpace:NSMakeRect(point.x, point.y, 0, 0)].origin;
}
+ (CGRect)flipRect:(CGRect)rect {
return [self cocoaToQuartzScreenSpaceConversionWithOriginFrame:rect];
}
/// Base function
+ (CGRect)cocoaToQuartzScreenSpaceConversionWithOriginFrame:(CGRect)originFrame {
/// Get zero screen height
NSScreen *zeroScreen = NSScreen.screens[0];
CGFloat screenHeight = zeroScreen.frame.size.height;
/// Extract values
CGFloat originY = originFrame.origin.y;
CGFloat frameHeight = originFrame.size.height;
/// Get new y
CGFloat destinationY = screenHeight - (originY + frameHeight);
/// Get new frame
CGRect destinationFrame = originFrame;
destinationFrame.origin.y = destinationY;
/// return
return destinationFrame;
}
精彩评论