为什么不透明度为 0.0 的 SwiftUI 矩形在透明 NSWindow 上呈现灰色矩形?
Why does a SwiftUI Rectangle with opacity 0.0 render a grey rectangle on a transparent NSWindow?
我有一个透明的 NSWindow
,其中包含 Rectangles
的网格,其不透明度可以切换。当不透明度为 0.0 时,会呈现一个灰色矩形(见图),我希望在其中看到一个空的 space.
我已经尝试将所有父视图中的背景颜色修改为 Color.clear
(在这段代码中乱七八糟),但怀疑原因在别处——可能是由于透明 windows 的行为方式,因为似乎还有阴影和轮廓等。
注意: 在不透明度 1.0 和 0.0 之间切换的行为略有不同,因此想知道如果不透明度 < 1.0 是否会支持视图 || > 0.0?
我的目标是macOS 11.1
我的NSWindow
是这样构造的:
class TransparentWindow: NSWindow {
init(contentRect: NSRect, backing: NSWindow.BackingStoreType, defer flag: Bool) {
super.init(contentRect: contentRect, styleMask: [.borderless, .fullSizeContentView], backing: .buffered, defer: false)
ignoresMouseEvents = true
titlebarAppearsTransparent = true
titleVisibility = .hidden
isOpaque = false
backgroundColor = NSColor.clear
level = .floating
isMovable = false
isReleasedWhenClosed = false
orderFront(nil)
toolbar?.isVisible = false
// Hide the traffic icons (standard close, minimize, maximize buttons)
standardWindowButton(.closeButton)?.isHidden = true
standardWindowButton(.miniaturizeButton)?.isHidden = true
standardWindowButton(.zoomButton)?.isHidden = true
styleMask.insert(NSWindow.StyleMask.fullSizeContentView)
}
}
观点大致如下:
struct GridView : View {
@EnvironmentObject var appStore : AppStore
var body: some View {
let columns: [GridItem] =
Array(repeating: .init(.fixed(size), spacing: spacing), count: cols)
LazyVGrid(columns: columns, spacing: spacing) {
ForEach(appStore.items) { item in
GridItemView(item: item)
.frame(width: size, height: size)
.background(Color.clear)
.border(Color.clear, width: 0.0)
}
}.padding(0)
.fixedSize()
.background(Color.clear)
}
}
struct GridItemView : View {
@EnvironmentObject var appStore : AppStore
@ObservedObject var item: Item
@State var opacity = 0.5
var body: some View {
GeometryReader { geometry in
Rectangle()
.fill(Color.white)
.onReceive(appStore.$frame) { frame in
let newFrame = calculateItemRect(
frame: frame,
crop: geometry.frame(in: .global)
)
if (!newFrame.equalTo(item.frame)) {
item.frame = newFrame
}
}.onReceive(item.$toggle) { toggle in
if toggle {
opacity = 0.0
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
opacity = 0.5
item.toggle = false
}
}
}.opacity(opacity)
}.background(Color.clear)
}
}
原来我需要在 NSWindow
实例上将 hasShadow
属性 设置为 false
:
class TransparentWindow: NSWindow {
// ...
hasShadow = false
ignoresMouseEvents = true
// ...
}
}
我有一个透明的 NSWindow
,其中包含 Rectangles
的网格,其不透明度可以切换。当不透明度为 0.0 时,会呈现一个灰色矩形(见图),我希望在其中看到一个空的 space.
我已经尝试将所有父视图中的背景颜色修改为 Color.clear
(在这段代码中乱七八糟),但怀疑原因在别处——可能是由于透明 windows 的行为方式,因为似乎还有阴影和轮廓等。
注意: 在不透明度 1.0 和 0.0 之间切换的行为略有不同,因此想知道如果不透明度 < 1.0 是否会支持视图 || > 0.0?
我的目标是macOS 11.1
我的NSWindow
是这样构造的:
class TransparentWindow: NSWindow {
init(contentRect: NSRect, backing: NSWindow.BackingStoreType, defer flag: Bool) {
super.init(contentRect: contentRect, styleMask: [.borderless, .fullSizeContentView], backing: .buffered, defer: false)
ignoresMouseEvents = true
titlebarAppearsTransparent = true
titleVisibility = .hidden
isOpaque = false
backgroundColor = NSColor.clear
level = .floating
isMovable = false
isReleasedWhenClosed = false
orderFront(nil)
toolbar?.isVisible = false
// Hide the traffic icons (standard close, minimize, maximize buttons)
standardWindowButton(.closeButton)?.isHidden = true
standardWindowButton(.miniaturizeButton)?.isHidden = true
standardWindowButton(.zoomButton)?.isHidden = true
styleMask.insert(NSWindow.StyleMask.fullSizeContentView)
}
}
观点大致如下:
struct GridView : View {
@EnvironmentObject var appStore : AppStore
var body: some View {
let columns: [GridItem] =
Array(repeating: .init(.fixed(size), spacing: spacing), count: cols)
LazyVGrid(columns: columns, spacing: spacing) {
ForEach(appStore.items) { item in
GridItemView(item: item)
.frame(width: size, height: size)
.background(Color.clear)
.border(Color.clear, width: 0.0)
}
}.padding(0)
.fixedSize()
.background(Color.clear)
}
}
struct GridItemView : View {
@EnvironmentObject var appStore : AppStore
@ObservedObject var item: Item
@State var opacity = 0.5
var body: some View {
GeometryReader { geometry in
Rectangle()
.fill(Color.white)
.onReceive(appStore.$frame) { frame in
let newFrame = calculateItemRect(
frame: frame,
crop: geometry.frame(in: .global)
)
if (!newFrame.equalTo(item.frame)) {
item.frame = newFrame
}
}.onReceive(item.$toggle) { toggle in
if toggle {
opacity = 0.0
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
opacity = 0.5
item.toggle = false
}
}
}.opacity(opacity)
}.background(Color.clear)
}
}
原来我需要在 NSWindow
实例上将 hasShadow
属性 设置为 false
:
class TransparentWindow: NSWindow {
// ...
hasShadow = false
ignoresMouseEvents = true
// ...
}
}