Swift中如何为菜单栏的NSImage实现透明度0到1的脉冲动画
macOS状态栏图标脉冲动画最优实现方案
因为NSStatusItem的内置button是标准NSButton实例,我们直接基于其backing layer做透明度动画即可,无需自定义视图,性能最优且不影响原有交互逻辑。
前置准备
首先需要在文件头部引入QuartzCore框架,才能使用Core Animation相关API:
import QuartzCore
在初始化statusBarItem后,先给button开启layer支持:
statusBarItem.button?.wantsLayer = true
脉冲动画实现代码
添加无限循环淡入淡出动画
func startStatusBarPulse() { // 先移除同名旧动画,避免重复添加导致异常 statusBarItem.button?.layer?.removeAnimation(forKey: "statusBarPulse") let pulseAnim = CABasicAnimation(keyPath: "opacity") pulseAnim.fromValue = 1.0 // 动画起始透明度 pulseAnim.toValue = 0.2 // 动画最低透明度,可根据需求调整 pulseAnim.duration = 0.8 // 单次淡入/淡出时长,单位秒,数值越小动画越快 pulseAnim.autoreverses = true // 动画自动反转,实现淡入后自动淡出效果 pulseAnim.repeatCount = .infinity // 无限循环播放 pulseAnim.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) // 自然的快慢节奏 statusBarItem.button?.layer?.add(pulseAnim, forKey: "statusBarPulse") }
停止脉冲动画
func stopStatusBarPulse() { statusBarItem.button?.layer?.removeAnimation(forKey: "statusBarPulse") // 重置透明度为默认值,避免停在半透明状态 statusBarItem.button?.layer?.opacity = 1.0 }
注意事项
- 动画添加时机需在
statusBarItem初始化完成后调用,避免layer为nil导致动画不生效 - 切换statusBar图标无需重新添加动画,动画作用在button层,与image无关
- 可根据业务需求调整
duration、toValue参数适配不同的动画效果 - 该方案系统占用极低,不会影响状态栏的正常响应速度
内容的提问来源于stack exchange,提问作者Maxime Dupré
相关产品推荐
相关产品推荐

