mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-14 06:30:49 +08:00
@@ -5,6 +5,12 @@ import path, { join } from 'path';
|
||||
const store = new Store();
|
||||
let lyricWindow: BrowserWindow | null = null;
|
||||
|
||||
// 跟踪拖动状态
|
||||
let isDragging = false;
|
||||
|
||||
// 添加窗口大小变化防护
|
||||
let originalSize = { width: 0, height: 0 };
|
||||
|
||||
const createWin = () => {
|
||||
console.log('Creating lyric window');
|
||||
|
||||
@@ -15,32 +21,73 @@ const createWin = () => {
|
||||
y?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
displayId?: number;
|
||||
}) || {};
|
||||
const { x, y, width, height } = windowBounds;
|
||||
|
||||
// 获取屏幕尺寸
|
||||
const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().workAreaSize;
|
||||
const { x, y, width, height, displayId } = windowBounds;
|
||||
|
||||
// 验证保存的位置是否有效
|
||||
const validPosition =
|
||||
x !== undefined && y !== undefined && x >= 0 && y >= 0 && x < screenWidth && y < screenHeight;
|
||||
// 获取所有屏幕的信息
|
||||
const displays = screen.getAllDisplays();
|
||||
let isValidPosition = false;
|
||||
let targetDisplay = displays[0]; // 默认使用主显示器
|
||||
|
||||
// 如果有显示器ID,尝试按ID匹配
|
||||
if (displayId) {
|
||||
const matchedDisplay = displays.find((d) => d.id === displayId);
|
||||
if (matchedDisplay) {
|
||||
targetDisplay = matchedDisplay;
|
||||
console.log('Found matching display by ID:', displayId);
|
||||
}
|
||||
}
|
||||
|
||||
// 验证位置是否在任何显示器的范围内
|
||||
if (x !== undefined && y !== undefined) {
|
||||
for (const display of displays) {
|
||||
const { bounds } = display;
|
||||
if (
|
||||
x >= bounds.x - 50 && // 允许一点偏移,避免卡在边缘
|
||||
x < bounds.x + bounds.width + 50 &&
|
||||
y >= bounds.y - 50 &&
|
||||
y < bounds.y + bounds.height + 50
|
||||
) {
|
||||
isValidPosition = true;
|
||||
targetDisplay = display;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 确保宽高合理
|
||||
const defaultWidth = 800;
|
||||
const defaultHeight = 200;
|
||||
const validWidth = width && width > 0 ? width : defaultWidth;
|
||||
const validHeight = height && height > 0 ? height : defaultHeight;
|
||||
const maxWidth = 1600; // 设置最大宽度限制
|
||||
const maxHeight = 800; // 设置最大高度限制
|
||||
|
||||
const validWidth = width && width > 0 && width <= maxWidth ? width : defaultWidth;
|
||||
const validHeight = height && height > 0 && height <= maxHeight ? height : defaultHeight;
|
||||
|
||||
// 确定窗口位置
|
||||
let windowX = isValidPosition ? x : undefined;
|
||||
let windowY = isValidPosition ? y : undefined;
|
||||
|
||||
// 如果位置无效,默认在当前显示器中居中
|
||||
if (windowX === undefined || windowY === undefined) {
|
||||
windowX = targetDisplay.bounds.x + (targetDisplay.bounds.width - validWidth) / 2;
|
||||
windowY = targetDisplay.bounds.y + (targetDisplay.bounds.height - validHeight) / 2;
|
||||
}
|
||||
|
||||
lyricWindow = new BrowserWindow({
|
||||
width: validWidth,
|
||||
height: validHeight,
|
||||
x: validPosition ? x : undefined,
|
||||
y: validPosition ? y : undefined,
|
||||
x: windowX,
|
||||
y: windowY,
|
||||
frame: false,
|
||||
show: false,
|
||||
transparent: true,
|
||||
hasShadow: false,
|
||||
alwaysOnTop: true,
|
||||
resizable: true,
|
||||
// 添加跨屏幕支持选项
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false,
|
||||
@@ -58,6 +105,9 @@ const createWin = () => {
|
||||
|
||||
// 监听窗口大小变化事件,保存新的尺寸
|
||||
lyricWindow.on('resize', () => {
|
||||
// 如果正在拖动,忽略大小调整事件
|
||||
if (isDragging) return;
|
||||
|
||||
if (lyricWindow && !lyricWindow.isDestroyed()) {
|
||||
const [width, height] = lyricWindow.getSize();
|
||||
const [x, y] = lyricWindow.getPosition();
|
||||
@@ -154,28 +204,75 @@ export const loadLyricWindow = (ipcMain: IpcMain, mainWin: BrowserWindow): void
|
||||
}
|
||||
});
|
||||
|
||||
// 开始拖动时设置标志
|
||||
ipcMain.on('lyric-drag-start', () => {
|
||||
isDragging = true;
|
||||
if (lyricWindow && !lyricWindow.isDestroyed()) {
|
||||
// 记录原始窗口大小
|
||||
const [width, height] = lyricWindow.getSize();
|
||||
originalSize = { width, height };
|
||||
|
||||
// 在拖动时暂时禁用大小调整
|
||||
lyricWindow.setResizable(false);
|
||||
}
|
||||
});
|
||||
|
||||
// 结束拖动时清除标志
|
||||
ipcMain.on('lyric-drag-end', () => {
|
||||
isDragging = false;
|
||||
if (lyricWindow && !lyricWindow.isDestroyed()) {
|
||||
// 确保窗口大小恢复原样
|
||||
lyricWindow.setSize(originalSize.width, originalSize.height);
|
||||
|
||||
// 拖动结束后恢复可调整大小
|
||||
lyricWindow.setResizable(true);
|
||||
}
|
||||
});
|
||||
|
||||
// 处理拖动移动
|
||||
ipcMain.on('lyric-drag-move', (_, { deltaX, deltaY }) => {
|
||||
if (!lyricWindow || lyricWindow.isDestroyed()) return;
|
||||
if (!lyricWindow || lyricWindow.isDestroyed() || !isDragging) return;
|
||||
|
||||
const [currentX, currentY] = lyricWindow.getPosition();
|
||||
const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().workAreaSize;
|
||||
const [windowWidth, windowHeight] = lyricWindow.getSize();
|
||||
|
||||
// 计算新位置,确保窗口不会移出屏幕
|
||||
const newX = Math.max(0, Math.min(currentX + deltaX, screenWidth - windowWidth));
|
||||
const newY = Math.max(0, Math.min(currentY + deltaY, screenHeight - windowHeight));
|
||||
// 使用记录的原始大小,而不是当前大小
|
||||
const windowWidth = originalSize.width;
|
||||
const windowHeight = originalSize.height;
|
||||
|
||||
lyricWindow.setPosition(newX, newY);
|
||||
// 计算新位置
|
||||
const newX = currentX + deltaX;
|
||||
const newY = currentY + deltaY;
|
||||
|
||||
// 保存新位置,但只保存位置信息,不使用getBounds()避免在Windows下引起尺寸变化
|
||||
const bounds = {
|
||||
x: newX,
|
||||
y: newY,
|
||||
width: windowWidth, // 使用当前保存的宽度
|
||||
height: windowHeight // 使用当前保存的高度
|
||||
};
|
||||
store.set('lyricWindowBounds', bounds);
|
||||
try {
|
||||
// 获取当前鼠标所在的显示器
|
||||
const mousePoint = screen.getCursorScreenPoint();
|
||||
const currentDisplay = screen.getDisplayNearestPoint(mousePoint);
|
||||
|
||||
// 拖动期间使用setBounds确保大小不变,使用false避免动画卡顿
|
||||
lyricWindow.setBounds(
|
||||
{
|
||||
x: newX,
|
||||
y: newY,
|
||||
width: windowWidth,
|
||||
height: windowHeight
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// 更新存储的位置
|
||||
const windowBounds = {
|
||||
x: newX,
|
||||
y: newY,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
displayId: currentDisplay.id // 记录当前显示器ID,有助于多屏幕处理
|
||||
};
|
||||
store.set('lyricWindowBounds', windowBounds);
|
||||
} catch (error) {
|
||||
console.error('Error during window drag:', error);
|
||||
// 出错时尝试使用更简单的方法
|
||||
lyricWindow.setPosition(newX, newY);
|
||||
}
|
||||
});
|
||||
|
||||
// 添加鼠标穿透事件处理
|
||||
|
||||
@@ -494,6 +494,8 @@ watch(
|
||||
// 添加拖动相关变量
|
||||
const isDragging = ref(false);
|
||||
const startPosition = ref({ x: 0, y: 0 });
|
||||
const lastMoveTime = ref(0);
|
||||
const moveThrottleMs = 10; // 限制拖动事件发送频率,提高性能
|
||||
|
||||
// 处理鼠标按下事件
|
||||
const handleMouseDown = (e: MouseEvent) => {
|
||||
@@ -501,7 +503,8 @@ const handleMouseDown = (e: MouseEvent) => {
|
||||
if (
|
||||
lyricSetting.value.isLock ||
|
||||
(e.target as HTMLElement).closest('.control-buttons') ||
|
||||
(e.target as HTMLElement).closest('.font-size-controls')
|
||||
(e.target as HTMLElement).closest('.font-size-controls') ||
|
||||
(e.target as HTMLElement).closest('.play-controls')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -511,23 +514,38 @@ const handleMouseDown = (e: MouseEvent) => {
|
||||
|
||||
isDragging.value = true;
|
||||
startPosition.value = { x: e.screenX, y: e.screenY };
|
||||
lastMoveTime.value = performance.now();
|
||||
|
||||
// 发送拖动开始信号到主进程
|
||||
windowData.electron.ipcRenderer.send('lyric-drag-start');
|
||||
|
||||
// 添加全局鼠标事件监听
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!isDragging.value) return;
|
||||
|
||||
// 时间节流,避免过于频繁的更新
|
||||
const now = performance.now();
|
||||
if (now - lastMoveTime.value < moveThrottleMs) return;
|
||||
lastMoveTime.value = now;
|
||||
|
||||
const deltaX = e.screenX - startPosition.value.x;
|
||||
const deltaY = e.screenY - startPosition.value.y;
|
||||
|
||||
// 发送移动事件到主进程
|
||||
windowData.electron.ipcRenderer.send('lyric-drag-move', { deltaX, deltaY });
|
||||
startPosition.value = { x: e.screenX, y: e.screenY };
|
||||
// 只有在实际移动时才发送事件
|
||||
if (Math.abs(deltaX) > 0 || Math.abs(deltaY) > 0) {
|
||||
// 发送移动事件到主进程
|
||||
windowData.electron.ipcRenderer.send('lyric-drag-move', { deltaX, deltaY });
|
||||
startPosition.value = { x: e.screenX, y: e.screenY };
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
if (!isDragging.value) return;
|
||||
isDragging.value = false;
|
||||
|
||||
// 发送拖动结束信号到主进程
|
||||
windowData.electron.ipcRenderer.send('lyric-drag-end');
|
||||
|
||||
// 移除事件监听
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
document.removeEventListener('mouseup', handleMouseUp);
|
||||
@@ -573,7 +591,7 @@ const handleNext = () => {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
body {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
@@ -589,9 +607,10 @@ body {
|
||||
user-select: none;
|
||||
transition: background-color 0.2s ease;
|
||||
cursor: default;
|
||||
border-radius: 14px;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
background: rgba(44, 44, 44, 0.466);
|
||||
.control-bar {
|
||||
&-show {
|
||||
opacity: 1;
|
||||
@@ -750,16 +769,15 @@ body {
|
||||
color: var(--text-color);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
transition: all 0.2s ease;
|
||||
line-height: 1.4;
|
||||
-webkit-text-stroke: 0.5px #0000008a;
|
||||
}
|
||||
|
||||
.lyric-translation {
|
||||
color: var(--text-secondary);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
transition: font-size 0.2s ease;
|
||||
line-height: 1.4; // 添加行高比例
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user