调整热力图位置和自动适配分辨率
This commit is contained in:
+58
-28
@@ -4728,32 +4728,50 @@ function PlayPageClient() {
|
|||||||
html: '<canvas id="custom-heatmap-canvas" style="width: 100%; height: 100%; display: block;"></canvas>',
|
html: '<canvas id="custom-heatmap-canvas" style="width: 100%; height: 100%; display: block;"></canvas>',
|
||||||
style: {
|
style: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
bottom: '16px',
|
bottom: '5px',
|
||||||
left: '10px',
|
left: '0',
|
||||||
right: '10px',
|
height: '60px',
|
||||||
height: '30px',
|
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
zIndex: '30',
|
zIndex: '30',
|
||||||
display: danmakuHeatmapEnabledRef.current ? 'block' : 'none',
|
display: danmakuHeatmapEnabledRef.current ? 'block' : 'none',
|
||||||
},
|
},
|
||||||
mounted: ($el: HTMLElement) => {
|
mounted: ($el: HTMLElement) => {
|
||||||
|
const canvas = $el.querySelector('#custom-heatmap-canvas') as HTMLCanvasElement;
|
||||||
|
if (!canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据实际显示尺寸和设备像素比设置 canvas 分辨率
|
||||||
|
const updateCanvasSize = () => {
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
const newWidth = Math.round(rect.width * dpr);
|
||||||
|
const newHeight = Math.round(rect.height * dpr);
|
||||||
|
|
||||||
|
// 只在尺寸真正改变时才更新,避免闪烁
|
||||||
|
if (canvas.width !== newWidth || canvas.height !== newHeight) {
|
||||||
|
canvas.width = newWidth;
|
||||||
|
canvas.height = newHeight;
|
||||||
|
return true; // 返回 true 表示尺寸已更新
|
||||||
|
}
|
||||||
|
return false; // 返回 false 表示尺寸未变化
|
||||||
|
};
|
||||||
|
|
||||||
// 动态获取进度条的实际位置并调整热力图
|
// 动态获取进度条的实际位置并调整热力图
|
||||||
const adjustHeatmapPosition = () => {
|
const adjustHeatmapPosition = () => {
|
||||||
// 尝试查找进度条的内部元素
|
const progressBar = document.querySelector('.art-control-progress') as HTMLElement;
|
||||||
const progressInner = document.querySelector('.art-control-progress-inner') as HTMLElement;
|
|
||||||
const progressBar = progressInner || document.querySelector('.art-control-progress') as HTMLElement;
|
|
||||||
|
|
||||||
if (progressBar) {
|
if (progressBar && $el.parentElement) {
|
||||||
const rect = progressBar.getBoundingClientRect();
|
const rect = progressBar.getBoundingClientRect();
|
||||||
const parentRect = $el.parentElement?.getBoundingClientRect();
|
const parentRect = $el.parentElement.getBoundingClientRect();
|
||||||
if (parentRect) {
|
|
||||||
const leftOffset = rect.left - parentRect.left;
|
|
||||||
|
|
||||||
// 调整热力图位置以匹配进度条
|
// 调整热力图位置以完全匹配进度条
|
||||||
$el.style.left = `${leftOffset}px`;
|
$el.style.left = `${rect.left - parentRect.left}px`;
|
||||||
$el.style.right = 'auto';
|
$el.style.bottom = `${parentRect.bottom - rect.bottom + 5}px`;
|
||||||
$el.style.width = `${rect.width}px`;
|
$el.style.width = `${rect.width}px`;
|
||||||
}
|
|
||||||
|
// 更新 canvas 分辨率
|
||||||
|
updateCanvasSize();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4789,23 +4807,30 @@ function PlayPageClient() {
|
|||||||
};
|
};
|
||||||
window.addEventListener('resize', resizeHandler);
|
window.addEventListener('resize', resizeHandler);
|
||||||
|
|
||||||
const canvas = $el.querySelector('#custom-heatmap-canvas') as HTMLCanvasElement;
|
|
||||||
if (!canvas) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.width = 1000;
|
|
||||||
canvas.height = 30;
|
|
||||||
|
|
||||||
let heatmapData: number[] = [];
|
let heatmapData: number[] = [];
|
||||||
let isHovering = false;
|
let isHovering = false;
|
||||||
let hoverTime = 0;
|
let hoverTime = 0;
|
||||||
let tooltipEl: HTMLElement | null = null;
|
let tooltipEl: HTMLElement | null = null;
|
||||||
|
|
||||||
// 监听热力图开关状态变化
|
// 监听热力图开关状态变化
|
||||||
|
let lastEnabled = localStorage.getItem('danmaku_heatmap_enabled') === 'true';
|
||||||
const updateVisibility = () => {
|
const updateVisibility = () => {
|
||||||
const enabled = localStorage.getItem('danmaku_heatmap_enabled');
|
const enabled = localStorage.getItem('danmaku_heatmap_enabled') === 'true';
|
||||||
$el.style.display = enabled === 'true' ? 'block' : 'none';
|
|
||||||
|
// 只在状态真正改变时才更新 DOM
|
||||||
|
if (enabled !== lastEnabled) {
|
||||||
|
$el.style.display = enabled ? 'block' : 'none';
|
||||||
|
|
||||||
|
// 如果从关闭变为打开,重新调整位置和尺寸
|
||||||
|
if (enabled) {
|
||||||
|
setTimeout(() => {
|
||||||
|
adjustHeatmapPosition();
|
||||||
|
drawHeatmap();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastEnabled = enabled;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 定期检查开关状态
|
// 定期检查开关状态
|
||||||
@@ -4840,11 +4865,14 @@ function PlayPageClient() {
|
|||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
|
|
||||||
const width = canvas.width;
|
const dpr = window.devicePixelRatio || 1;
|
||||||
const height = canvas.height;
|
const width = canvas.width / dpr;
|
||||||
|
const height = canvas.height / dpr;
|
||||||
const duration = artPlayerRef.current.duration || 0;
|
const duration = artPlayerRef.current.duration || 0;
|
||||||
const currentTime = artPlayerRef.current.currentTime || 0;
|
const currentTime = artPlayerRef.current.currentTime || 0;
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.scale(dpr, dpr);
|
||||||
ctx.clearRect(0, 0, width, height);
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
|
||||||
const progressRatio = duration > 0 ? currentTime / duration : 0;
|
const progressRatio = duration > 0 ? currentTime / duration : 0;
|
||||||
@@ -4909,6 +4937,8 @@ function PlayPageClient() {
|
|||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 格式化时间
|
// 格式化时间
|
||||||
|
|||||||
Reference in New Issue
Block a user