mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-30 21:07:24 +08:00
+122
-25
@@ -5,6 +5,12 @@ import path, { join } from 'path';
|
|||||||
const store = new Store();
|
const store = new Store();
|
||||||
let lyricWindow: BrowserWindow | null = null;
|
let lyricWindow: BrowserWindow | null = null;
|
||||||
|
|
||||||
|
// 跟踪拖动状态
|
||||||
|
let isDragging = false;
|
||||||
|
|
||||||
|
// 添加窗口大小变化防护
|
||||||
|
let originalSize = { width: 0, height: 0 };
|
||||||
|
|
||||||
const createWin = () => {
|
const createWin = () => {
|
||||||
console.log('Creating lyric window');
|
console.log('Creating lyric window');
|
||||||
|
|
||||||
@@ -15,32 +21,73 @@ const createWin = () => {
|
|||||||
y?: number;
|
y?: number;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
displayId?: number;
|
||||||
}) || {};
|
}) || {};
|
||||||
const { x, y, width, height } = windowBounds;
|
|
||||||
|
|
||||||
// 获取屏幕尺寸
|
const { x, y, width, height, displayId } = windowBounds;
|
||||||
const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().workAreaSize;
|
|
||||||
|
|
||||||
// 验证保存的位置是否有效
|
// 获取所有屏幕的信息
|
||||||
const validPosition =
|
const displays = screen.getAllDisplays();
|
||||||
x !== undefined && y !== undefined && x >= 0 && y >= 0 && x < screenWidth && y < screenHeight;
|
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 defaultWidth = 800;
|
||||||
const defaultHeight = 200;
|
const defaultHeight = 200;
|
||||||
const validWidth = width && width > 0 ? width : defaultWidth;
|
const maxWidth = 1600; // 设置最大宽度限制
|
||||||
const validHeight = height && height > 0 ? height : defaultHeight;
|
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({
|
lyricWindow = new BrowserWindow({
|
||||||
width: validWidth,
|
width: validWidth,
|
||||||
height: validHeight,
|
height: validHeight,
|
||||||
x: validPosition ? x : undefined,
|
x: windowX,
|
||||||
y: validPosition ? y : undefined,
|
y: windowY,
|
||||||
frame: false,
|
frame: false,
|
||||||
show: false,
|
show: false,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
hasShadow: false,
|
hasShadow: false,
|
||||||
alwaysOnTop: true,
|
alwaysOnTop: true,
|
||||||
|
resizable: true,
|
||||||
|
// 添加跨屏幕支持选项
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, '../preload/index.js'),
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
@@ -58,6 +105,9 @@ const createWin = () => {
|
|||||||
|
|
||||||
// 监听窗口大小变化事件,保存新的尺寸
|
// 监听窗口大小变化事件,保存新的尺寸
|
||||||
lyricWindow.on('resize', () => {
|
lyricWindow.on('resize', () => {
|
||||||
|
// 如果正在拖动,忽略大小调整事件
|
||||||
|
if (isDragging) return;
|
||||||
|
|
||||||
if (lyricWindow && !lyricWindow.isDestroyed()) {
|
if (lyricWindow && !lyricWindow.isDestroyed()) {
|
||||||
const [width, height] = lyricWindow.getSize();
|
const [width, height] = lyricWindow.getSize();
|
||||||
const [x, y] = lyricWindow.getPosition();
|
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 }) => {
|
ipcMain.on('lyric-drag-move', (_, { deltaX, deltaY }) => {
|
||||||
if (!lyricWindow || lyricWindow.isDestroyed()) return;
|
if (!lyricWindow || lyricWindow.isDestroyed() || !isDragging) return;
|
||||||
|
|
||||||
const [currentX, currentY] = lyricWindow.getPosition();
|
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 windowWidth = originalSize.width;
|
||||||
const newY = Math.max(0, Math.min(currentY + deltaY, screenHeight - windowHeight));
|
const windowHeight = originalSize.height;
|
||||||
|
|
||||||
lyricWindow.setPosition(newX, newY);
|
// 计算新位置
|
||||||
|
const newX = currentX + deltaX;
|
||||||
|
const newY = currentY + deltaY;
|
||||||
|
|
||||||
// 保存新位置,但只保存位置信息,不使用getBounds()避免在Windows下引起尺寸变化
|
try {
|
||||||
const bounds = {
|
// 获取当前鼠标所在的显示器
|
||||||
x: newX,
|
const mousePoint = screen.getCursorScreenPoint();
|
||||||
y: newY,
|
const currentDisplay = screen.getDisplayNearestPoint(mousePoint);
|
||||||
width: windowWidth, // 使用当前保存的宽度
|
|
||||||
height: windowHeight // 使用当前保存的高度
|
// 拖动期间使用setBounds确保大小不变,使用false避免动画卡顿
|
||||||
};
|
lyricWindow.setBounds(
|
||||||
store.set('lyricWindowBounds', bounds);
|
{
|
||||||
|
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 isDragging = ref(false);
|
||||||
const startPosition = ref({ x: 0, y: 0 });
|
const startPosition = ref({ x: 0, y: 0 });
|
||||||
|
const lastMoveTime = ref(0);
|
||||||
|
const moveThrottleMs = 10; // 限制拖动事件发送频率,提高性能
|
||||||
|
|
||||||
// 处理鼠标按下事件
|
// 处理鼠标按下事件
|
||||||
const handleMouseDown = (e: MouseEvent) => {
|
const handleMouseDown = (e: MouseEvent) => {
|
||||||
@@ -501,7 +503,8 @@ const handleMouseDown = (e: MouseEvent) => {
|
|||||||
if (
|
if (
|
||||||
lyricSetting.value.isLock ||
|
lyricSetting.value.isLock ||
|
||||||
(e.target as HTMLElement).closest('.control-buttons') ||
|
(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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -511,23 +514,38 @@ const handleMouseDown = (e: MouseEvent) => {
|
|||||||
|
|
||||||
isDragging.value = true;
|
isDragging.value = true;
|
||||||
startPosition.value = { x: e.screenX, y: e.screenY };
|
startPosition.value = { x: e.screenX, y: e.screenY };
|
||||||
|
lastMoveTime.value = performance.now();
|
||||||
|
|
||||||
|
// 发送拖动开始信号到主进程
|
||||||
|
windowData.electron.ipcRenderer.send('lyric-drag-start');
|
||||||
|
|
||||||
// 添加全局鼠标事件监听
|
// 添加全局鼠标事件监听
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
if (!isDragging.value) return;
|
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 deltaX = e.screenX - startPosition.value.x;
|
||||||
const deltaY = e.screenY - startPosition.value.y;
|
const deltaY = e.screenY - startPosition.value.y;
|
||||||
|
|
||||||
// 发送移动事件到主进程
|
// 只有在实际移动时才发送事件
|
||||||
windowData.electron.ipcRenderer.send('lyric-drag-move', { deltaX, deltaY });
|
if (Math.abs(deltaX) > 0 || Math.abs(deltaY) > 0) {
|
||||||
startPosition.value = { x: e.screenX, y: e.screenY };
|
// 发送移动事件到主进程
|
||||||
|
windowData.electron.ipcRenderer.send('lyric-drag-move', { deltaX, deltaY });
|
||||||
|
startPosition.value = { x: e.screenX, y: e.screenY };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
if (!isDragging.value) return;
|
if (!isDragging.value) return;
|
||||||
isDragging.value = false;
|
isDragging.value = false;
|
||||||
|
|
||||||
|
// 发送拖动结束信号到主进程
|
||||||
|
windowData.electron.ipcRenderer.send('lyric-drag-end');
|
||||||
|
|
||||||
// 移除事件监听
|
// 移除事件监听
|
||||||
document.removeEventListener('mousemove', handleMouseMove);
|
document.removeEventListener('mousemove', handleMouseMove);
|
||||||
document.removeEventListener('mouseup', handleMouseUp);
|
document.removeEventListener('mouseup', handleMouseUp);
|
||||||
@@ -573,7 +591,7 @@ const handleNext = () => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
body {
|
body {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
@@ -589,9 +607,10 @@ body {
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
transition: background-color 0.2s ease;
|
transition: background-color 0.2s ease;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
border-radius: 14px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(44, 44, 44, 0.466);
|
||||||
.control-bar {
|
.control-bar {
|
||||||
&-show {
|
&-show {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -750,16 +769,15 @@ body {
|
|||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
-webkit-text-stroke: 0.5px #0000008a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lyric-translation {
|
.lyric-translation {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
|
||||||
transition: font-size 0.2s ease;
|
transition: font-size 0.2s ease;
|
||||||
line-height: 1.4; // 添加行高比例
|
line-height: 1.4; // 添加行高比例
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user