Electron: 支持点击透明

创建于 2015-03-31  ·  77评论  ·  资料来源: electron/electron

正如这里所评论的, https: //github.com/atom/atom-shell/pull/949#issuecomment -87087841 - 不幸的是,除非您可以点击透明区域,否则透明窗口的用途有限。

我注意到在文档中指出这是被上游错误阻止的。 nw.js 项目确实支持这个,但我不确定他们的实现有多大不同......

我认为这个问题值得跟踪讨论和实施,所以就在这里。

componentransparent enhancement

最有用的评论

该线程中的一些人已经建议使用 GPU 基于透明度添加点击率,但这真的有用吗? 大多数窗口需要阴影来使窗口层次结构清晰。 我一直在研究一个始终在顶部的浮动小部件/帮助工具,它确实需要阴影才能脱颖而出。 由于这些有一个 alpha>0,点击是不可能的。 在对上面发布的库进行了更多工作之后,我发现大多数语言功能已经存在以支持本地点击。

是否有可能实现这个库的本地工作方式?

JS/CSS 等效

body {pointer-events: none}
window.addEventListener('mousemove', event =>
  if (event.target === document.documentElement) // <html>-element
    setIgnoreMouseEvents(true, {forward: true)   // {forward: true} keeps generating MouseEvents
  else
    setIgnoreMouseEvents(false)
)

pointer-events CSS 规则是标准化的,可以防止元素成为event.target 。 您可以在BrowserWindow选项中添加类似{transparent: true, clickThrough: 'pointer-events'}的内容以激活此功能。

在实际实现它并支持拖动事件等时还有更多内容,但它似乎不会导致任何接近瓶颈的问题。 MouseEvent无论如何都会生成,因此性能不应该真正受到影响。 可以缓存 ignoreMouseEvents 状态,因此只有 mouseenter/mouseleave 触发本机窗口代码。

animated png <a href="recorded@60fps">recorded@60fps</a>, <a href="played@60fps">played@60fps</a>

编辑:如果 setIgnoreMouseEvents 跨平台正常工作,这段代码实际上就足够了。 目前,它是解决方法的组合,包括以屏幕刷新率轮询鼠标,而不是在某些情况下侦听事件。

所有77条评论

虽然 nw.js 确实支持它,但它有一些非常严重的缺点。 首先它需要禁用 GPU 加速,其次它只适用于 OS X 和 Windows(基于他们的文档)。

+1,这也困扰着 Slack,因为我们在透明窗口中显示所有通知。

+1,这对我正在从事的项目至关重要。

+1,这会很棒。

有兴趣了解最新消息。 出于我的目的,如果我们可以设置一个透明的窗口来具有 _no_ 单击区域,我会很高兴。 因此,您可以拥有一个始终在顶部的全屏覆盖,而不会捕捉到点击。

我也很感兴趣,我正在构建一个带有半透明窗口的应用程序,该窗口位于其他应用程序之上,但 mouseevents 需要通过其他应用程序。

+1

有关于它的消息吗?

链接的铬错误被标记为无法修复
https://code.google.com/p/chromium/issues/detail?id=387234

最后一条评论是:

11 [email protected]

你知道,顺便说一句,如果用户需要,Atom 团队的人可以自己做,对吗?

所以目前不会发生任何事情,直到 atom 团队中的某个人决定这样做或说服 chrome 团队值得将其放在积压工作中(他们说这是低优先级)。

今天刚遇到这个问题,它给我的使用新窗口的计划带来了一个巨大的问题。 (事实上​​,现在是不可能的)

我很想解决这个问题!

是否有任何正在进行的工作? Electron 团队是否有机会在不添加到 Chromium 的情况下使这成为可能?

+1

假设这不会通过 Chromium 代码解决,是否有一种合理的方法让应用程序监听点击事件,然后在 GTK 或类似的东西中触发正确的对应物?

我使用 ahkscript

#c::
    WinSet, ExStyle, ^0x20, A
    WinSet, Transparent, 255, A
    return

在活动窗口上按 Win+C,然后点击它

@zcbenz 有任何更新吗? 😄

对于关注此问题的人:如果您只是想点击整个窗口,则可以使用v1.2.2 中引入的新

同样在使指定区域透明方面,我提出了一些关于实施的想法(但不要假设它会在不久的将来完成):

对于Linux,使用XShapeCombineRectangles API其实很简单, SetIgnoreMouseEvents的实现只是设置了(0, 0, 1, 1)的区域来接受鼠标事件。

对于 Windows,设置窗口的形状很容易,但是没有 API 来控制哪些区域可以接受鼠标事件。

对于 OS X,如果您无法控制渲染代码,则无法设置窗口形状或设置点击区域。

由于 Chromium 执行复杂的硬件加速,因此实现自定义点击区域变得非常困难。 NW.js 通过禁用硬件加速和修补渲染代码来实现,这是我绝对不想采用的方法。

我在 OS X/Windows 上实现的想法是,我们只是让整个窗口点击,然后创建一个透明窗口作为子窗口,并使用它来捕获所有鼠标事件。 由于我们完全控制了子窗口,我们可以将其设置为用户不想点击的区域的形状,然后将子窗口中接收到的所有鼠标和键盘事件发送到父窗口。

这样我们就不用给 Chromium 打补丁,所以维护起来很方便,硬件加速也能用。 缺点是我们必须非常小心地重定向鼠标和键盘事件,以使窗口表现得好像没有子窗口一样。

如果像我一样,您对此功能的用例相当简单,那么这个要点可能会引起人们的兴趣。 这是@zcbenz所描述的基本实现,创建一个可点击区域,将鼠标事件重定向到父级。

在开发需要点击的 Windows 小工具项目的过程中,我无意中提出了一个有点花哨但实用的解决方案,它可以定义真正任意形状的可点击区域。

在渲染进程中,使用“screen.getCursorScreenPoint()”来持续跟踪光标位置,然后将坐标定时发送给主进程。 在主进程中,使用“webContents.capturePage()”在渲染器窗口上捕获精确的 1x1 像素的图像。 由于它只有1个像素,因此性能成本可以忽略不计,然后您可以通过查看不透明度值来定义该像素是否可点击。 这样,您实际上可以定义一个真正像素正确的可点击区域。 这里剩下的唯一问题是无论光标位置如何都可以检测鼠标按下状态的功能。

@ButzYung你能告诉我如何从 NativeImage 获取不透明度值(webContents.capturePage() 返回 NativeImage)? 谢谢。

@varavut 以捕获 1x1 图像为例,它会是这样的。

``
webContents.capturePage({x:0,y:0, width:1 , height:1 }, function(image) {
var buffer = image.getBitmap()

// send the data back to renderer for processing, with buffer[3] being the alpha channel
webContents.send('capturePage', 'RESULT|' + [buffer[0],buffer[1],buffer[2],buffer[3]])

});
``

@ButzYung感谢您的解决方案。 我试过了,关键是跟踪的间隔。 我的电脑 100 毫秒,看起来不错。 如果我使用webContents.capturePage ,CPU 成本很高。 我会定义点击通过的区域,只需检查该区域中的点。

@cecilpeng在我的情况下,我会在当前 webContents.capturePage 完成后延迟 200 毫秒,而不是立即进行另一次捕获。 这大约是 4-5 次捕获/秒,足以用于检查透明度,并且 CPU 使用率可以忽略不计。

@ButzYung是的,最好在最后一次完成后再进行一次捕获。 我还在担心超时解决方案,它不够聪明。 我们无法知道用户计算机上发生了什么。 我建议 javascript 是一种很好的语言来观察而不是检查。

我是一个 HTML 菜鸟,但不可能简单地:

  1. 在您想要点击的 HTML 元素上设置一个 'onMouseLeave' 事件。
    --> 这个鼠标离开事件执行 win.setIgnoreEvents(true)
  2. 在您想要点击的 HTML 元素上设置一个“onMouseEnter”事件。
    --> 这个鼠标进入事件执行 win.setIgnoreEvents(false)

由于我缺乏 HTML 知识,在某些情况下可能会出现问题......但在我看来,这似乎是目前理想的解决方法。 当然,除了需要额外的设置时间?

@sancarn您的方法的问题在于,当 .setIgnoreMouseEvents 在步骤 1 中设置为 true 时,不再有鼠标事件,因此步骤 2 中通常的 HTML 驱动的“onMouseOver”事件将不再触发。

但是,嘿,现在我考虑一下,如果您的方法与我的“capturePage”方法相结合,可以通过比较不透明度而不使用通常的 HTML 事件来检测鼠标悬停的开/关,它可能会产生有趣的结果。 我实际上已经尝试过,你猜怎么着,它有效,哈哈。 现在,您可以拥有一个真正像素正确的可点击区域。

哈哈。 有趣的是,我没有将其视为缺陷 xD

事实上,合并这两种方法也稍微不那么重,这很好。

在获取像素方面,我还没有测试过,但在 Windows 上使用带有消息WM_MOUSEMOVE = 512 的hookWindowMessages()可能更容易。

当我设置transparent=true我无法双击以最大化窗口。 (更多问题见这里)我需要设置透明度的唯一原因是创建一个圆角窗口。 如果这个问题解决了,我们就可以彻底解决很多问题,省很多力气。 真的很期待有人来实现这一点。

嗨,我只是想 +1 这个错误,因为这对我的用例来说是一个非常好的补充。 这真的会对我们的用户体验产生影响。 一个巨大的。

_使用FastHub从我的 Google Pixel XL

如果您在 Windows 上使用与我类似的用例,您可能会发现我最近接受的 PR 很有用。 它向setIgnoreMouseEvents添加一个参数,使窗口像往常一样点击,但仍然允许您侦听 DOM 事件,例如mouseleave 。 如果您可以根据鼠标移动确定窗口何时应该点击,您应该能够选择退出并恢复正常,如本例所示。 对于更多的上下文,我的用例是我想要在网页上有一个洞(可能被其他元素覆盖)。 该示例显示了我如何在进入/离开元素时启用/禁用点击。 透明度本身是通过实验性 CSS 功能使用背景过滤器制作的。

不幸的是,我不知道 Linux 或 Mac GUI 编程,所以我不知道那里是否有类似的方法。 不过,我想我会通知它,以防有人发现它有用。

@andens听起来真的很棒! 请有人为 Linux 和 Mac 实现相同的功能! 那对我来说就足够了!

_使用FastHub从我的 Google Pixel XL

@andens我似乎遇到了一个奇怪的问题,为了让它正常工作,我需要同时传递 false 和 true,否则它将无法工作。 这样做之后,我需要至少重新加载一次网页内容。 毕竟这一切,似乎完美无缺:)
(使用 v1.8.0)

不起作用(如下示例)

      divThing.addEventListener('mouseleave', () => {
        win.setIgnoreMouseEvents(true, {forward: true});
      });


      divThing.addEventListener('mouseenter', () => {
        win.setIgnoreMouseEvents(false);
      });

重新加载至少一次后工作

      divThing.addEventListener('mouseleave', () => {
        win.setIgnoreMouseEvents(true, {forward: true});
      });

      divThing.addEventListener('mouseenter', () => {
        win.setIgnoreMouseEvents(false, {forward: true});
      });

core.js 上奇怪的临时修复

@edunad抱歉耽搁了; 我现在被其他东西淹没了。 如果我没记错的话,当第一个参数为 false 时,forward 应该没有任何区别,但我可能会弄错。 您在离开 div 时向前发布的代码在进入时停止,而文档示例则相反。 这是故意的吗? 即便如此,语义应该是相同的,只是转发区域本质上是颠倒的,但也许 Chromium 的行为方式存在一些极端情况。

我能想到的一件事是,在您第一次进入 div 之前,您可能不会收到 leave 事件(因此开始转发)。 你考虑过这个吗? 希望我能找到一些时间来尝试一下。

@andens没问题! 花你需要的所有时间,我不着急。 (最终使用 disableHardwareAcc() 恢复到 1.7 +)

我需要的是与示例相反的内容(如果不悬停在 div 上,则忽略输入)。
我确实尝试过这个例子,但我遇到了同样的问题:(

基本上它是屏幕两侧的一个小 div,

我已经向它添加了控制台日志,似乎mouseenter / mouseleave 会被触发,但是一旦mouseleave 被触发,我就无法重新触发mouseenter 以禁用ignoreMouse。

如果电子元素不是完全不可见(不透明度 0),那么使用硬件加速和单击电子元素会很好

+1,这对我正在从事的项目至关重要。

一个对我来说完美无缺的伟大解决方案是@ButzYung的答案,而不是检查不透明度,我只是检查鼠标是否在我的按钮容器 div 内,如果它在里面我启用鼠标事件,如果它在外面我禁用它们和窗口再次点击。

我们是否有任何 Linux / Mac 程序员可以尝试实现相同的功能?
PR Andreas 提到在 Windows 中做了什么? 我真的会
真的很喜欢看到它工作 <3

2018 年 2 月 22 日星期四下午 2:59,AlexCatch [email protected]写道:

一个对我来说完美无缺的伟大解决方案是@ButzYung 的答案
https://github.com/butzyung ,而不是检查不透明度,我只是
检查鼠标是否在我的按钮容器 div 内,如果它在我的内部
启用鼠标事件,如果它在外面我禁用它们并且窗口变成
再次点击。


您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/electron/electron/issues/1335#issuecomment-367688459
或静音线程
https://github.com/notifications/unsubscribe-auth/AIc892p83oXBrGkNdlwSrLTJVtDgZjOaks5tXXKvgaJpZM4D3dRY
.

有没有人对此有 mac 的解决方法? 或者知道为什么 setIgnoreMouseEvents(true, {forward: true}) 不适用于 mac?

我正在考虑使用 osx-mouse 并检查鼠标全局鼠标位置是否在 html 元素上以重新启用鼠标事件。

window.setIgnoreMouseEvents(true)实际上适用于 macOS。

@paulius005它仅在 Windows 上实现,因为它使用本机 WinAPI。 这种功能高度依赖于操作系统特性,并且(我猜想)它可能很难实现,除非操作系统提供明确的支持。

您的建议听起来与为 Windows 所做的非常相似。 如果您了解底层 macOS 编程,请随时研究https://github.com/electron/electron/pull/10183以获取灵感,我会尽我所能帮助您提出想法。

有关于此功能的消息吗? 我试图在 Windows 10 应用程序上使用 setIgnoreMouseEvents 没有成功。 我也在使用启用了透明选项的应用程序。

@leidsongermano我目前正在使用 v1.8.7 和app.disableHardwareAcceleration(); ,似乎工作正常。 唯一的缺点是禁用硬件加速。 有了这个,你就不需要setIgnoreMouseEvents

@edunad我正在测试使用电子 0.36.* 的电子快速入门。 之后我更新到最新的 versionp (2.0.2),现在它工作得很好。 谢谢!

@edunad对我

我的应用程序https://github.com/singuerinc/overlay在没有点击透明度的情况下是无用的,所以我停止开发,直到这个问题得到解决。

我曾经用 Flash/AIR 构建这个应用程序没有任何问题,我不明白为什么不能在 Electron 中实现它。

@edunad @adeperio disableHardwareAcceleration允许我们在透明度上忽略 Mac/Windows 上的鼠标事件,但仍单击“实体”html 元素?

@singuerinc是的,如果您启用disableHardwareAcceleration并将应用程序透明度设置为 true,则只有 Solid 和if you set the opacity to 0.1可点击。 请注意macs的速度变慢(查看

@edunad我只是尝试了很多不同的方法,但它不起作用。
我设置了一个没有任何元素的空透明全尺寸窗口,但我无法点击,我不知道我做错了什么。
window.setIgnoreMouseEvents(true)是唯一的方法,但正如我所说,我的应用程序变得毫无用处。

@singuerinc抱歉耽搁了,请尝试使用旧版本的电子,我目前正在使用1.8.7

我编写了一个简单的解决方法类,您可以在其中选择白名单或黑名单功能来单击 HTMLElements。 它可用作电子透明鼠标修复,也适用于圆角! 今天是从头开始写的,所以可能还有一些问题。

让我们希望你们中的一些人可以使用它。 它也可以通过 npm 获得。

编辑:不适用于 linux :(

electron-transparency-mouse-fix demo gif

我一直在寻找 setIgnoreMouseEvents 的实际实现,除了找到其选项的接口之外,我还很干。 有点沮丧,我可以解释一下它的行为实际上是在哪里定义的吗?

为了促进对话,我还使用 AHK 作为我的 HUD 的一种变通方法。
我没有发现该界面难以实际使用,并且必须在我的窗口上的事件侦听器中将 setIgnoreMouseEvents 翻转为 true,当它准备好显示一切按预期工作时。

但是我想了解实现,至少找到它。

如果您使用 Electron >3.0.0(目前处于测试阶段)并且您只需要完全透明的区域即可点击,请尝试 #13789 中引入的 setWindowShape API。

看起来在 Mac 上不可用。

@etisdew我相信你要找的东西可以在atom/browser/native_window_views.cc (Windows/Linux) 和atom/browser/native_window_mac.mm (Mac) 中找到。

该线程中的一些人已经建议使用 GPU 基于透明度添加点击率,但这真的有用吗? 大多数窗口需要阴影来使窗口层次结构清晰。 我一直在研究一个始终在顶部的浮动小部件/帮助工具,它确实需要阴影才能脱颖而出。 由于这些有一个 alpha>0,点击是不可能的。 在对上面发布的库进行了更多工作之后,我发现大多数语言功能已经存在以支持本地点击。

是否有可能实现这个库的本地工作方式?

JS/CSS 等效

body {pointer-events: none}
window.addEventListener('mousemove', event =>
  if (event.target === document.documentElement) // <html>-element
    setIgnoreMouseEvents(true, {forward: true)   // {forward: true} keeps generating MouseEvents
  else
    setIgnoreMouseEvents(false)
)

pointer-events CSS 规则是标准化的,可以防止元素成为event.target 。 您可以在BrowserWindow选项中添加类似{transparent: true, clickThrough: 'pointer-events'}的内容以激活此功能。

在实际实现它并支持拖动事件等时还有更多内容,但它似乎不会导致任何接近瓶颈的问题。 MouseEvent无论如何都会生成,因此性能不应该真正受到影响。 可以缓存 ignoreMouseEvents 状态,因此只有 mouseenter/mouseleave 触发本机窗口代码。

animated png <a href="recorded@60fps">recorded@60fps</a>, <a href="played@60fps">played@60fps</a>

编辑:如果 setIgnoreMouseEvents 跨平台正常工作,这段代码实际上就足够了。 目前,它是解决方法的组合,包括以屏幕刷新率轮询鼠标,而不是在某些情况下侦听事件。

这里有消息吗? 🙃

@metaa我在 Mac 中用setIgnoreMouseEvents (Electron 3) 部分修复了它(看起来更像是一个黑客)

https://github.com/singuerinc/overlay/blob/master/app/components/helpers/mouseEvents.ts#L3

所以基本上每次你在你的应用程序中查看一个元素时,你必须setIgnoreMouseEvents(false)并且当你离开时相反。 所以它是相当昂贵的,这取决于你的应用程序。 我会说它工作得很好,尽管有时它真的很难调试,因为整个 Electron 变得“不可点击”,在这种情况下你不能使用 devtools。

带有当前版本 Electron 的 MacOs 似乎没有我几个月前在 Windows/Linux 上遇到的问题。 🙌

这是一个最小的设置,对我来说是开箱即用的:

const setIgnoreMouseEvents = require('electron').remote.getCurrentWindow().setIgnoreMouseEvents
addEventListener('pointerover', function mousePolicy (event) {
  mousePolicy._canClick = event.target === document.documentElement ?
    mousePolicy._canClick && setIgnoreMouseEvents(true, {forward: true}) :
    mousePolicy._canClick || setIgnoreMouseEvents(false) || 1
})
setIgnoreMouseEvents(true, {forward: true}) // BUG: this must be triggered after the devtools loaded IF you load the console 'detached'
body {pointer-events: none}
.clickable {pointer-events: auto}

我真的很喜欢它使用原生 CSS 功能的方式。 您可以在 devtools 中即时点击项目,代码占用空间最少,而且在性能方面也非常好。 CSS 中继承的工作方式也适合这个用例。

@toonvanvr这是否适用于任何 macOS 版本,前提是我们使用最新的 Electron 版本,如您所说?

@mynetx不幸的是,我对此一无所知,因为 macOS 10.14 Mojave 是我使用过的唯一版本。 需要支持的关键特性是{forward: true}而其余的应该是平台无关的。

我正在使用带有 MacOs 10.14.5 的电子 4.0.0,即使我使用了{forward: true}我仍然无法获得鼠标事件(即使我监听mouseover事件)。
我用过: win.setIgnoreMouseEvents(true, { forward: true});但是所有鼠标事件都被阻止了。
在带有电子 4.0.0 的 win8.1 上它正在工作。

我确实注意到只有当我在当前窗口下方打开另一个窗口时才会发生这种情况
@toonvanvr - 它应该工作吗? 我错过了什么吗?

@david-winder-kaltura
我已经有一段时间没有真正使用过 Electron,但是上次我检查时,它在不打开 devTools 的情况下运行良好。 一旦你打开控制台,就会出现竞争条件等,以检查鼠标事件和透明度。

我受到这个解决方案的启发,在我的项目中执行以下操作:

从主要,

监听对发出的"hideWindow"消息的回复:

const { ipcMain } = require('electron');

// emitter
ipcMain.on('hideWindow', () => {
  mainWindow.hide();
});

mainWindow = new BrowserWindow({
  webPreferences: {
    nodeIntegration: true
  },
  frame: false,
  transparent: true,
  hasShadow: false,
  ...
});

从您的申请中,

如果单击了具有 id mainElement的元素,则向"hideWindow"发送响应:

const { ipcRenderer } = window.require('electron');

// so that we can write window.require
declare global {
  interface Window {
    require: any;
  }
}

...

function hideWindow(event: any) {
  let hideWindow = true;

  // some looping so that we can check for the id on all parent/child elements
  event.path.map(object => {
    if (object.id == 'mainElement') {
      hideWindow = false;
    }
  });

  // let Electron know we want to hide the window
  hideWindow && ipcRenderer.send('hideWindow');
}

document.addEventListener('mousedown', hideWindow);

一个缺点

  • 您需要将 id "mainElement"到所有单独的组件中。 如果您要渲染多个单独的元素,这可能会很烦人。

从这里拿走什么

我发现对于与Spotlight类似的应用程序来说,这是一个干净的解决方案。 我可以使用键盘命令显示应用程序,如果我在实际 DOM 元素的区域外单击,则将其隐藏。

大家有没有试过设置

app.commandLine.appendSwitch( 'disable-gpu-compositing' );

在应用就绪事件之前?

@DEDaniel 有用吗?

@LauraAubin的解决方案效果很好,我自己也在使用。

另一个缺点是,点击实际上不会通过透明区域传播。 因此,如果用户试图单击窗口下方的某些内容,他们将不得不单击两次才能真正完成它。

@vifird对我来说是的,这是使用 Electron 6.0.2 版在 Windows 7 和 10 上运行的。
我遇到这个问题是因为我想禁用我的 css 网格中的一个区域并使其透明。
拥有透明区域后,我意识到底层应用程序没有收到任何点击事件。 因此,我在 main.js Electron 文件中添加了上述行,问题就解决了。

一个例子可以在这里找到。

有人能告诉我是否有办法捕获点击事件的坐标吗?

我想要一个可点击的透明覆盖(我使用此线程中的解决方案实现了这一点),但也想捕获这些点击的坐标(不知道如何执行此操作)。 如果有人能告诉我这是否可行,并指出我的解决方案,我将不胜感激。
(感觉有点绝望,已经花了好几个小时试图实现这一目标,但没有结果:()

有人能告诉我是否有办法捕获点击事件的坐标吗?

@codemanki嘿!

鉴于您的叠加层扩展了您想要捕获的整个区域,您应该能够使用一些带有event处理程序的 JS 获取鼠标的坐标,例如onClick甚至onMouseMove

我编写了一个 Codepen 来演示这一点,尽管您可以采用多种方法。

https://codepen.io/LauraAubin/pen/NWPKrrq

另请注意,我相信此解决方案仅在透明覆盖覆盖鼠标悬停的整个空间时才有效。 也就是说,如果您在 Electron 应用程序之外单击,这将不起作用。

@LauraAubin嘿! 感谢您的回答和演示:)。 问题是,一旦您将setIgnoreMouseEvents为 true,电子窗口就根本不会检测到鼠标点击(就像您对setIgnoreMouseEvents期望的那样)。 我尝试以与您演示的方式相同的方式捕获它们,但不幸的是,鼠标单击事件甚至没有进入BrowserWindow ,它只会进入覆盖层后面的任何内容。

让它工作让我想立即放弃这个库。 完全浪费时间并且非常令人沮丧,尤其是-webkit-app-regionsetIgnoreMouseEvents忽略了......真是一团糟。 幸运的是,我有一个对我有用的解决方案。

确保启用webPreferences.nodeIntegration ,然后在您的 HTML 中:

css

body {pointer-events: none}
* {pointer-events: all;}
.draggable {-webkit-app-region: drag;}

JS

setIgnoreMouseEvents = window.require('electron').remote.getCurrentWindow().setIgnoreMouseEvents

var t

window.addEventListener('mousemove', event => {
  if (event.target === document.documentElement) {
    setIgnoreMouseEvents(true, {forward: true})
    if (t) clearTimeout(t)
    t = setTimeout(function() {
      setIgnoreMouseEvents(false)
    }, 150)
  } else setIgnoreMouseEvents(false)
})

这里的想法是默认情况下您不想忽略鼠标事件。 但是,如果鼠标移动到作为事件目标的 html 或 body 元素上,我们希望忽略可能发生的点击并传递它们。 这不包括 body 的任何子元素,它们将接收点击,并且不会传递。

AKA 正文和 HTML 事件目标 => 传递
身体的孩子 => 不通过

超时是必要的,因为如果您将mousemove从传递元素(如 body 或 html)传递到.draggable元素(即应用了-webkit-app-region ),则它不会t 接收点击事件,因为setIgnoreMouseEvents从未设置回false 。 因此,我们尝试将其默认设置为false (超时后)。

@singuerinc是的,如果您启用disableHardwareAcceleration并将应用程序透明度设置为 true,则只有 Solid 和if you set the opacity to 0.1可点击。 请注意macs的速度变慢(查看

这适用于 Windows10,但不适用于 MacOSX。

嘿人们。 如果有的话,当今商定的最佳实践是什么?

@nikkwong这是唯一适用于 MacOS 和 Windows 的解决方案。 你让我今天一整天都感觉很好!

@nikkwong ,如果与电子窗口透明区域后面的窗口交互,这会导致鼠标行为

如果只有一种方法来设置根据您是否希望窗口响应点击而返回 true 或 false 的回调,那就太好了。 在 Mac 上,这可以通过从https://github.com/electron/electron/blob/master/shell/browser/native_browser_view_mac.mm#L36有条件地返回 nil 或 self 来实现

@nikkwong 的回答也对我

const electron = require('electron');
const {ipcRenderer} = require('electron');
const BrowserWindow = electron.remote.BrowserWindow;
  setIgnoreMouseEvents = BrowserWindow.getAllWindows()[0].setIgnoreMouseEvents;

然后当您在 main.js 中创建窗口时,请执行以下操作:

  const win = new BrowserWindow({
    width: 800,
    height: 600,
    frame: false,
    transparent: true,
    webPreferences: {
      nodeIntegration: true,
      enableRemoteModule: true,
    }
  })

因为透明窗口失去焦点,所以

window.addEventListener('mousemove', cb)

无法触发

此页面是否有帮助?
0 / 5 - 0 等级