Skip to content

Instantly share code, notes, and snippets.

@SureEnough
Created April 18, 2024 03:27
Show Gist options
  • Save SureEnough/31015104cb5e8fc927e2281470692c3a to your computer and use it in GitHub Desktop.
Save SureEnough/31015104cb5e8fc927e2281470692c3a to your computer and use it in GitHub Desktop.
electron window drag
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Hello World!</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="box"></div>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, screen } = require('electron')
const path = require('path')
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 100,
height: 100,
frame: false, // 要创建无边框窗口
resizable: false, // 禁止窗口大小缩放
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.setAlwaysOnTop(true, "screen-saver");
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
const { left, top } = {
left: screen.getPrimaryDisplay().workAreaSize.width - 160,
top: (screen.getPrimaryDisplay().workAreaSize.height - 90) / 2
}
mainWindow.setPosition(left, top);
ipcMain.on('move-win', (event, args) => {
const x1 = args.x < 0 ? 0 : args.x;
const y1 = args.y < 0 ? 0 : args.y;
mainWindow.setBounds({ x: x1, y: y1, width: 100, height: 100 })
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
{
"name": "embarrassed-tale-smell-co59w",
"productName": "embarrassed-tale-smell-co59w",
"description": "My Electron application description",
"keywords": [],
"main": "./main.js",
"version": "1.0.0",
"author": "w",
"scripts": {
"start": "electron ."
},
"dependencies": {},
"devDependencies": {
"electron": "30.0.0"
}
}
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
ipcRenderer: (type,data) => ipcRenderer.send(type, data)
})
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// No Node.js APIs are available in this process because
// `nodeIntegration` is turned off. Use `preload.js` to
// selectively enable features needed in the rendering
// process.
const winRef = document.querySelector('.box');
let isDragging = false;
let draggingRef = false;
let startTimeRef = 0;
let position = null;
let positionRef = null;
const sendPostion = () => {
if (position) {
window.electronAPI.ipcRenderer('move-win', position)
}
}
const handleMouseDown = (event) => {
// setDragging(true);
draggingRef = true
startTimeRef = Date.now();
isDragging = false;
};
const handleMouseMove = async (event) => {
if (!(draggingRef && winRef)) return;
const currentElement = winRef;
const parentElement = winRef.parentElement;
if (!parentElement) return false;
let x = 0
let y = 0
if (event.type === "touchmove") {
const touch = event.touches[0];
x = touch.screenX
y = touch.screenY
} else {
x = event.screenX
y = event.screenY
}
const divRect = parentElement.getBoundingClientRect();
const offsetX = (x - divRect.left) / divRect.width * parentElement.offsetWidth;
const offsetY = (y - divRect.top) / divRect.height * parentElement.offsetHeight;
x = Math.round(offsetX - currentElement.clientWidth / 2);
y = Math.round(offsetY - currentElement.clientHeight / 2);
// if (Date.now() - startTimeRef < 300) {
// return;
// }
if (positionRef) {
let x2 = 0;
let y2 = 0;
if (x >= positionRef.x) {
x2 = x - positionRef.x;
} else {
x2 = positionRef.x - x;
}
if (y >= positionRef.y) {
y2 = y - positionRef.y;
} else {
y2 = positionRef.y - y;
}
// console.log('positionRef:', x2, y2);
if (x2 > 300 || y2 > 300) {
return;
}
}
console.log(event.type + ':', x, y);
isDragging = true;
position = { x, y }
positionRef = { x, y }
sendPostion()
}
const handleMouseUp = () => {
setTimeout(() => {
isDragging = false;
}, 0);
draggingRef = false
}
const handleClick = (event) => {
event.stopPropagation();
event.preventDefault();
if (!isDragging) {
console.log('handleClick')
}
};
winRef.addEventListener("touchstart", handleMouseDown);
window.addEventListener('touchmove', handleMouseMove);
document.addEventListener('touchend', handleMouseUp);
winRef.addEventListener("mousedown", handleMouseDown);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
/* Empty */
body {
overflow: hidden;
margin: 0;
}
.box {
width: 100vw;
height: 100vh;
background-color: red;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment