From e9f1a6a46fe60f95e9f7d2cfe8f21ab6cbd24d80 Mon Sep 17 00:00:00 2001 From: dekun Date: Sat, 30 May 2026 10:42:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0K=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/charts.js | 48 +++++++++++++++++++----------------------------- web/style.css | 41 ++++++----------------------------------- 2 files changed, 25 insertions(+), 64 deletions(-) diff --git a/web/charts.js b/web/charts.js index da83ae7..752dd2f 100644 --- a/web/charts.js +++ b/web/charts.js @@ -1,4 +1,4 @@ -/** 多周期 K 线 · SQLite 后端 + localStorage · 弹窗全屏 Lightweight Charts */ +/** 多周期 K 线 · SQLite 后端 + localStorage · 弹窗大图 Lightweight Charts */ const CHART_INTERVALS = ["5m", "15m", "30m", "1h", "4h", "1d", "1w"]; const INTERVAL_LIMITS = { @@ -30,6 +30,8 @@ const COLORS = { }; const MINI_SIZE = { w: 380, h: 100 }; +/** 弹窗图表最小尺寸;实际按视口放大(带鱼屏可接近全宽) */ +const MODAL_CHART_MIN = { w: 1280, h: 560 }; const DEFAULT_MINI_INTERVAL = "1d"; let chartModalSymbol = ""; @@ -47,15 +49,12 @@ function limitForInterval(interval) { return INTERVAL_LIMITS[interval] || 500; } -function modalSize() { - const fs = document.fullscreenElement; - if (fs) { - return { - w: Math.max(800, window.innerWidth - 48), - h: Math.max(480, window.innerHeight - 160), - }; - } - return { w: 1280, h: 680 }; +function modalChartSize() { + const padX = 32; + const chromeY = 150; + const w = Math.max(MODAL_CHART_MIN.w, window.innerWidth - padX * 2); + const h = Math.max(MODAL_CHART_MIN.h, window.innerHeight - chromeY); + return { w, h }; } function loadKlineFromLS(symbol, interval) { @@ -171,7 +170,7 @@ function drawCandlestickChart(canvas, candles, options = {}) { if (!canvas || !candles.length) return; const large = options.large === true; - const size = large ? modalSize() : MINI_SIZE; + const size = large ? modalChartSize() : MINI_SIZE; const volRatio = large ? 0.22 : 0.32; const pad = large ? { t: 16, r: 16, b: 28, l: 56 } @@ -298,7 +297,7 @@ async function loadMiniChart(box) { drawCandlestickChart(canvas, candles, { large: false }); box.dataset.loaded = "1"; if (status) status.textContent = `${candles.length}日·${sourceLabel(source)}`; - box.title = `${symbol} 日K ${candles.length}根 (${sourceLabel(source)}),点击全屏`; + box.title = `${symbol} 日K ${candles.length}根 (${sourceLabel(source)}),点击查看大图`; } catch (e) { if (status) status.textContent = "—"; box.title = `${symbol}: ${e.message}`; @@ -328,7 +327,7 @@ function ensureLwcChart(container) { } destroyLwcChart(); - const { w, h } = modalSize(); + const { w, h } = modalChartSize(); container.style.width = `${w}px`; container.style.height = `${h}px`; @@ -407,7 +406,7 @@ function updateModalMeta(candles, source, interval) { title.textContent = `${chartModalSymbol} · ${interval.toUpperCase()} K线`; } if (hint) { - hint.textContent = `${candles.length} 根 · ${sourceLabel(source)} · 滚轮缩放 · 拖拽平移 · 十字线 · Esc 退出`; + hint.textContent = `${candles.length} 根 · ${sourceLabel(source)} · 滚轮缩放 · 拖拽平移 · 十字线 · Esc 或点击遮罩关闭`; } } @@ -439,9 +438,6 @@ function closeChartModal() { modal.classList.add("hidden"); destroyLwcChart(); chartModalSymbol = ""; - if (document.fullscreenElement) { - document.exitFullscreen?.().catch(() => {}); - } } async function openChartModal(symbol) { @@ -465,12 +461,6 @@ async function openChartModal(symbol) { if (container) container.innerHTML = ""; await loadModalChart(DEFAULT_MINI_INTERVAL); - - const inner = modal.querySelector(".chart-modal-inner"); - const req = inner.requestFullscreen || inner.webkitRequestFullscreen; - if (req) { - req.call(inner).catch(() => {}); - } } function setupChartModal() { @@ -514,14 +504,14 @@ function setupChartModal() { document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeChartModal(); }); - document.addEventListener("fullscreenchange", () => { + window.addEventListener("resize", () => { if (!chartModalSymbol || !lwcChart) return; const container = document.getElementById("chart-modal-container"); - if (!container) return; - const rect = container.getBoundingClientRect(); - if (rect.width > 0 && rect.height > 0) { - lwcChart.applyOptions({ width: rect.width, height: rect.height }); - } + if (!container?.isConnected) return; + const { w, h } = modalChartSize(); + container.style.width = `${w}px`; + container.style.height = `${h}px`; + lwcChart.applyOptions({ width: w, height: h }); }); } diff --git a/web/style.css b/web/style.css index f024c5c..c26e260 100644 --- a/web/style.css +++ b/web/style.css @@ -334,34 +334,11 @@ button:hover { border: 1px solid var(--border); border-radius: 12px; padding: 1.25rem 1.5rem 1.5rem; - max-width: 96vw; + width: calc(100vw - 2rem); + max-width: none; max-height: 96vh; overflow: auto; -} - -.chart-modal-inner:fullscreen { - width: 100vw; - height: 100vh; - max-width: none; - max-height: none; - border-radius: 0; - display: flex; - flex-direction: column; -} - -.chart-modal-inner:fullscreen .chart-modal-canvas-wrap { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; - min-height: 0; -} - -.chart-modal-inner:fullscreen .chart-lwc-container { - flex: 1; - width: 100% !important; - height: 100% !important; - min-height: 0; + box-shadow: 0 16px 48px rgba(0, 0, 0, 0.45); } .chart-modal-head { @@ -402,7 +379,9 @@ button:hover { .chart-lwc-container { width: 100%; - min-height: 480px; + min-width: 1280px; + min-height: 560px; + margin: 0 auto; } .chart-lwc-fallback { @@ -411,14 +390,6 @@ button:hover { color: var(--muted); } -.chart-modal-inner:fullscreen .chart-modal-head { - flex-shrink: 0; -} - -.chart-modal-inner:fullscreen .chart-modal-hint { - flex-shrink: 0; -} - .stats-table .stats-total-vol { font-weight: 600; white-space: nowrap;