You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 10:52:47