如何获取macOS桌面像素以自定义半透明模糊视图?
自定义macOS窗口背景模糊:获取桌面像素的问题
本问题并非要实现模糊或半透明功能/算法,而是将使用Apple内置API来实现图像半透明。 任何半透明功能都需要像素来启动模糊处理,本问题核心是获取该过程所需的桌面像素素材。
提出该问题的原因在于:macOS-SwiftUI的Material或macOS-Cocoa的NSVisualEffectView无法自定义视图背后桌面的半透明模糊半径,可选方案十分有限。因此我决定获取桌面像素,再按照期望的半径实现模糊效果。
尝试后遇到的问题
- 应用运行卡顿,流畅度不足以投入使用
- 无法获取应用窗口所在区域的桌面像素,因为窗口本身遮挡了该区域的像素,目前只能通过读取窗口左侧区域来规避此问题
我清楚当前的实现方式并不正确,但思路本身是成立的:NSVisualEffectView或Material都需要访问背后的像素才能工作,既然它们无法满足自定义需求,我尝试自行获取像素并使用Apple API实现自定义半径的模糊效果。
代码实现
AppDelegate部分
import Cocoa import SwiftUI var window: NSWindow = NSWindow() class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { window.styleMask = [.titled, .closable, .miniaturizable, .fullSizeContentView] window.backingType = .buffered window.delegate = sharedDelegate window.title = "Window" window.isOpaque = false window.contentView = NSHostingView(rootView: ContentView()) window.center() window.setFrameAutosaveName("Main Window") window.isMovableByWindowBackground = true window.makeKeyAndOrderFront(window) } } class MyNSWindowDelegate: NSObject, NSWindowDelegate { func windowWillMove(_ notification: Notification) { postMyNotification(value: notification) } func windowDidMove(_ notification: Notification) { postMyNotification(value: notification) } } let sharedDelegate: MyNSWindowDelegate = MyNSWindowDelegate() let myNotificationName: Notification.Name = Notification.Name(rawValue: "myNotificationName") func postMyNotification(value: Notification) { NotificationCenter.default.post(Notification(name: myNotificationName, object: value)) } let nsApplication: NSApplication = NSApplication.shared let appDelegate: AppDelegate = AppDelegate() nsApplication.delegate = appDelegate nsApplication.run()
ContentView部分
import SwiftUI struct ContentView: View { @State private var cgImage: CGImage? = nil var body: some View { Color.gray.overlay(content: { if let unwrappedImage: CGImage = cgImage { Image(decorative: unwrappedImage, scale: 1.0) .resizable() .scaledToFill() .blur(radius: 2, opaque: false) } }) .animation(.default, value: cgImage) .frame(width: 400, height: 400) .onReceive(NotificationCenter.default.publisher(for: myNotificationName)) { newNotification in if let unwrappedNewNotification = newNotification.object as? Notification { if let unwrappedNSWindow = unwrappedNewNotification.object as? NSWindow { cgImage = pixelColorReader(point: unwrappedNSWindow.frame.origin, size: unwrappedNSWindow.frame.size) } } } } } func pixelColorReader(point: CGPoint, size: CGSize) -> CGImage { let y = NSScreen.main!.frame.height - (point.y + size.height - 28/2.0) let screenID = NSScreen.main!.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as! UInt32 let image: CGImage = CGDisplayCreateImage(CGDirectDisplayID(screenID), rect: CGRect(x: point.x - size.width, y: y, width: size.width, height: size.height))! return image }
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

