В безрамочное окно добавлена настраиваемая строка заголовка, чтобы окно можно было перетаскивать. Строка заголовка отображается, но eventListener не срабатывает:
основной.js:
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
frame: false,
scrollbar: false,
webPreferences:{
nodeIntegration: true,
contextIsolation: false,
}
})
win.loadFile('index.html')
}
индекс.html:
<body>
<div class = "window">
<div class = "window-content">
<textarea>some content</textarea>
</div>
</div>
<script src = "index.js"></script>
</body>
индекс.js:
let titleBar = document.createElement('div')
titleBar.style.width = "100%"
titleBar.style.height = "32px"
titleBar.style.backgroundColor = "#fff"
titleBar.style.position = "absolute"
titleBar.style.top = titleBar.style.left = 0
titleBar.style.webkitAppRegion = "drag"
titleBar.textContent = 'My App';
document.body.appendChild(titleBar)
// Nothing happens
titleBar.addEventListener("mouseover", () => {
console.info("hello")
})
Вам не нужно использовать eventListener, вы можете добиться этого, используя только CSS.
main.js
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
frame: false,
scrollbar: false,
titleBarStyle: 'hidden',//Add this
titleBarOverlay: {
color: '#ecf2f9',
symbolColor: '#003d99',
height: 40,
},//Add this for windows
webPreferences:{
nodeIntegration: true,
contextIsolation: false,
}
})
win.loadFile('index.html')
}
index.html
<body>
<div class = "titleBar">
My App
</div>
<div class = "window">
<div class = "window-content">
<textarea>some content</textarea>
</div>
</div>
<script src = "index.js"></script>
index.css
.titleBar{
background-color: #ecf2f9;
height: 40px; /* Adjust height as needed */
-webkit-app-region: drag; /*Allow dragging the window */
.
.
.
}
Да, можно добавить прослушиватель событий в пользовательскую строку заголовка, используемую для перетаскивания окон в безрамочном окне, но для этого требуется реализация собственного кода событий мыши для перетаскивания окна.
Проблема с событиями мыши, не запускающими eventListener, вызвана
titleBar.style.webkitAppRegion = "drag"
что мешает механизму распространения событий и предотвращает обнаружение событий мыши прослушивателем.
Другими словами, кажется, что в Electron вы не можете одновременно использовать и то, и другое для одного и того же DOM-объекта: перетаскивание с помощью .style.webkitAppRegion = "drag"
и получение событий мыши с помощью .addEventListener("mouseover",
. Если вам нужно поведение перетаскивания, вам нужно реализовать его самостоятельно, используя события мыши, полученные от DOM-объекта.
Чтобы увидеть это самостоятельно, прокомментируйте или удалите строку «перетаскивания» и убедитесь, что событие мыши работает должным образом (не забывайте, что вывод консоли предоставляется после Ctrl+Shift+i в окне приложения, а не в окне приложения). Окно терминала, в котором запущено приложение).
Имейте в виду, что, используя некоторые «программные трюки», вы обычно можете достичь любого желаемого эффекта в любой программной системе, поэтому утверждения о том, что что-то невозможно, обычно не совсем корректны с этой точки зрения, поскольку они лишь утверждают, что не существует простого и хорошо известного способа достижения чего-либо.
Возможный обходной путь — иметь две строки заголовка (или значок перетаскивания рядом со строкой заголовка в одной строке): один для перетаскивания окна, а другой — для реагирования на события мыши:
console.info("renderer.js loaded");
document.addEventListener('DOMContentLoaded', () => {
// Create the draggable title bar at the very top
let draggableTitleBar = document.createElement('div');
draggableTitleBar.style.width = "100%";
draggableTitleBar.style.height = "24px";
draggableTitleBar.style.backgroundColor = "#e74c3c";
draggableTitleBar.style.position = "absolute";
draggableTitleBar.style.top = "0px";
draggableTitleBar.style.left = "0px";
draggableTitleBar.style.zIndex = "1000";
draggableTitleBar.style.webkitAppRegion = "drag";
draggableTitleBar.textContent = 'Draggable Title Bar';
// Create the non-draggable title bar below it
let nonDraggableTitleBar = document.createElement('div');
nonDraggableTitleBar.style.width = "100%";
nonDraggableTitleBar.style.height = "40px";
nonDraggableTitleBar.style.backgroundColor = "#3498db";
nonDraggableTitleBar.style.position = "absolute";
nonDraggableTitleBar.style.top = "24px"; // Adjust position as needed
nonDraggableTitleBar.style.left = "0px";
nonDraggableTitleBar.style.zIndex = "1000";
nonDraggableTitleBar.textContent = 'Non-Draggable Title Bar';
// Add event listeners to the non-draggable title bar
nonDraggableTitleBar.addEventListener("mouseover", () => {
console.info("Mouseover event triggered on non-draggable title bar");
});
nonDraggableTitleBar.addEventListener("click", () => {
console.info("Non-draggable title bar clicked");
});
// Append both title bars to the document body
document.body.appendChild(draggableTitleBar);
document.body.appendChild(nonDraggableTitleBar);
console.info("Title bars added to the DOM");
});
Вот как это выглядит:
Для полноты ниже приведен код приложения, которое использует строку заголовка как для перетаскивания окна, так и для приема событий мыши (записывается в консоль):
~ $ cat package.json
{
"name": "oOosysElectronApp",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"keywords": [],
"author": "oOosys",
"license": "---",
"description": "PureGraphicWindowArea",
"dependencies": {
"electron": "^31.1.0"
}
}
~ $ cat main.js
const { app, BrowserWindow, ipcMain } = require('electron');
// const path = require('path');
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 480,
frame: false,
scrollbar: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
}
});
win.loadFile('index.html');
ipcMain.on('get-window-position', (event) => {
event.returnValue = win.getPosition();
});
ipcMain.on('set-window-position', (event, x, y) => {
// console.info("set-window-position to x,y : ", x , y) // prints to TERMINAL
win.setPosition(x, y);
});
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
~ $ cat renderer.js
const { ipcRenderer } = require('electron');
console.info("renderer.js loaded");
document.addEventListener('DOMContentLoaded', () => {
// Create the title bar
let titleBar = document.createElement('div');
titleBar.style.width = "100%";
titleBar.style.height = "32px";
titleBar.style.backgroundColor = "lightblue"; // Temporary background color for visibility
titleBar.style.position = "absolute";
titleBar.style.top = "0px";
titleBar.style.left = "0px";
titleBar.style.zIndex = "1000"; // Ensure the title bar is on top
titleBar.textContent = 'Window Dragging Title';
document.body.appendChild(titleBar);
console.info("Title bar added to the DOM");
let isDragging = false;
let startX, startY;
let startWindowX, startWindowY;
titleBar.addEventListener("mousedown", (event) => {
event.preventDefault();
event.stopPropagation();
isDragging = true;
startX = event.clientX;
startY = event.clientY;
const [windowX, windowY] = ipcRenderer.sendSync('get-window-position');
startWindowX = windowX;
startWindowY = windowY;
console.info("MouseDOWN windowX,Y, mouseX,Y:", startWindowX, startWindowY, startX, startY);
});
// mousemove event interferes somehow with
// ipcRenderer.send('set-window-position', newWindowX, newWindowY);
// causing the window to resize instead of re-position
// In other words CONTINUOUS DRAGGING of the window FAILS TO WORK as expected
document.addEventListener("mouseup", (event) => {
if ( isDragging ) {
const currentX = event.clientX;
const currentY = event.clientY;
const deltaX = currentX - startX;
const deltaY = currentY - startY;
const newWindowX = startWindowX + deltaX;
const newWindowY = startWindowY + deltaY;
ipcRenderer.send('set-window-position', newWindowX, newWindowY);
console.info("mouseUP newWindowX,Y mouseMovedDistXY:", newWindowX, newWindowY, deltaX, deltaY);
isDragging = false;
}
});
});
~ $ cat index.html
<!DOCTYPE html>
<html><head><title>oOosys Electron App</title>
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #d0eed0;
}
</style></head>
<body>
<script src = "renderer.js"></script>
<br><br><br><br><br><br><br><br><br>
<textarea>some content</textarea>
</body></html>
~ $ npm start 2>/dev/null
> [email protected] start
> electron .
А вот как это выглядит после выполнения кода, задокументированного в приведенном выше журнале сеанса оболочки:
Обратите внимание, что при событии mouseup
окно перемещается в целевую позицию.
Событие mousemove
, похоже, мешает работе ipcRenderer.send('set-window-position', newWindowX, newWindowY);
, что приводит к изменению размера окна вместо перемещения.
поэтому этот подход, похоже, не может обеспечить плавное непрерывное перетаскивание окна из-за проблемы с функциональностью Electron.
Спасибо за обходной путь, но для меня это не вариант. Итак, в конце концов ответ (цитирую вас): «в Electron вы не можете одновременно иметь и то, и другое: перетаскивание и запуск событий мыши».
@nBar: см. мой обновленный ответ, где приведен пример приложения, использующего строку заголовка для обеих целей: получения событий мыши и перетаскивания окна.
Это действительно обходной путь, который работает хорошо! Перетаскивание не совсем плавное, но работает. Таким образом, с вашим решением в Electron фактически возможно иметь перетаскиваемую настраиваемую строку заголовка, которая также может получать события мыши.
Большое спасибо за показ альтернативного способа создания пользовательской строки заголовка. Однако это также не позволяет обнаружить какие-либо прослушиватели событий. Итак, как говорит @oOosys, с перетаскиваемой строкой заголовка EventListeners кажется невозможным.