From 8ab4e6283851a7d5e133437d7238cc1a96c3aff3 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 26 Oct 2026 19:46:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E6=BB=91=E6=9D=86=E6=94=B9=E7=94=A8?= =?UTF-8?q?=E5=8E=9F=E7=89=88=E8=BF=9B=E5=BA=A6=E6=B8=90=E5=8F=98=E5=B9=B6?= =?UTF-8?q?=E6=A0=A1=E5=87=86=E5=BC=80=E5=85=B3=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3DTank/docs/SettingsStyleTable.md | 22 ++++++- .../kotlin/App/Browser/Ui/LobbyScreens.kt | 58 ++++++------------- .../app/src/jsMain/resources/lobby3.css | 27 +++++++++ 3 files changed, 65 insertions(+), 42 deletions(-) diff --git a/3DTank/docs/SettingsStyleTable.md b/3DTank/docs/SettingsStyleTable.md index 94821fe..f4a387b 100644 --- a/3DTank/docs/SettingsStyleTable.md +++ b/3DTank/docs/SettingsStyleTable.md @@ -61,7 +61,7 @@ | `InputRangeComponentStyle` | `display:flex; flex-direction:column; justify-content:space-between; align-items:flex-start; height:3.188em; min-height:3.188em; margin-bottom:1.75em` | | `InputRangeComponentStyle` label | `color:white; font-size:0.9375em; margin-top:0` | | `InputRangeComponentStyle` input | `-webkit-appearance:none; width:100%; height:0.563em; background:transparent; cursor:pointer` | -| range track | `height:0.375em; background:rgba(255,255,255,0.2)` | +| range track | `height:0.375em; background:transparent`;进度用 `linear-gradient(to right,#ffbc09 0%,#ffbc09 X%,rgba(255,255,255,0.1) X%,rgba(255,255,255,0.1) 100%)` | | range thumb | `width:1.875em; height:1em; border-radius:0.25em; background:rgb(255,188,9); margin-top:-0.3em` | | `GameSettingsStyle.containerFormOptions` | `display:flex; flex-direction:column; margin-left:0.9em; margin-bottom:1em` | | `GameSettingsStyle.notificationText` | `color:rgba(255,255,255,0.5); text-align:left` | @@ -72,3 +72,23 @@ - 下拉选项弹层:已按 `DropDownStyle` + `ContextMenuStyle` 还原菜单/选项高度、背景、hover、选中色;使用 `position:fixed` + 控件 `getBoundingClientRect()`,宽度等于选择框、紧贴下沿,避免被设置面板滚动容器裁剪。 - 菜单滑动条:当前按 `index * 5em + 1.25em` 计算,原版由组件状态计算 `margin-top`。 - 部分设置项的分组/顺序仍以官方 key 和现有状态为准,后续可继续按原组件 render 树核对。 + +## 6. 原版组件定义位置 + +| 组件 / 样式 | 混淆版类 / 函数 | 位置 | +|---|---|---| +| `SettingsComponentStyle` | `kNi` | `module_82347.js:89525` | +| `SettingsMenuComponentStyle` | `EMi` | `module_82347.js:90329` | +| `SettingsButtonsComponentStyle` | `UPi` | `module_82347.js:89326` | +| `GameSettingsStyle` | `BAi` | `module_82347.js:88190` | +| `DropDownStyle` | `J7t` | `module_82347.js:34073` | +| `ContextMenuStyle`(下拉菜单/选项) | `u7t` | `module_82347.js:33638` | +| `CheckBoxComponentStyle` | `QBi` | `module_82347.js:92742` | +| `CheckBoxStyle`(Toggle Switch) | `Z0t` | `module_82347.js:33272` | +| `InputRangeComponentStyle` | `EUi` | `module_82347.js:92980` | +| `InputRangeComponentStyle-blockSoundVolume` | `wUi` | `module_82347.js:92880` | +| `InputRangeComponentStyle-range` | `kUi` | `module_82347.js:92930` | +| 滑杆进度渐变 | `hUi.tap` | `module_82347.js:200507` | +| `SettingsComponentStyle-slider` | `kNi.z1jp_1` | `module_82347.js:89620` | + +`ksc-130` 是 `SettingsComponentStyle-slider` 的 Emotion 生成类名;当前实现用 `data-ui="SettingsComponentStyle-slider"` 标记,等价于给滑杆挂上该样式。 diff --git a/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/LobbyScreens.kt b/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/LobbyScreens.kt index dea4ee9..7597f27 100644 --- a/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/LobbyScreens.kt +++ b/TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/LobbyScreens.kt @@ -2383,38 +2383,13 @@ private val SettingsRange: csstype.PropertiesBuilder.() -> Unit = { Style("appearance", "none") Style("width", "100%") Style("height", "0.563em") - Style("background-color", Palette.White20) Style("outline", "none") - Style("accent-color", "rgb(255, 188, 9)") + Style("border-radius", "0") } -private val SettingsSliderTrack: csstype.PropertiesBuilder.() -> Unit = { - Style("position", "relative") - Style("width", "100%") - Style("height", "0.375em") - Style("background-color", Palette.White20) -} - -private fun SettingsSliderThumb(Value: Int): csstype.PropertiesBuilder.() -> Unit = { - Style("position", "absolute") - Style("top", "50%") - Style("left", "${Value.coerceIn(0, 100)}%") - Style("width", "1.875em") - Style("height", "1em") - Style("border-radius", "0.25em") - Style("background-color", Palette.Yellow) - Style("transform", "translate(-50%, -50%)") - Style("pointer-events", "none") -} - -private val SettingsSliderInput: csstype.PropertiesBuilder.() -> Unit = { - Style("position", "absolute") - Style("inset", "0") - Style("width", "100%") - Style("height", "100%") - Style("opacity", "0") - Style("cursor", "pointer") - Style("margin", "0") +private fun SettingsSliderGradient(Value: Int): String { + val Percent = Value.coerceIn(0, 100) + return "linear-gradient(to right, #ffbc09 0%, #ffbc09 $Percent%, rgba(255, 255, 255, 0.1) $Percent%, rgba(255, 255, 255, 0.1) 100%)" } private val SettingsButtons: csstype.PropertiesBuilder.() -> Unit = { @@ -2460,8 +2435,7 @@ private val SettingsCheckboxRow: csstype.PropertiesBuilder.() -> Unit = { Style("align-items", "center") Style("justify-content", "flex-start") Style("width", "100%") - Style("height", "auto") - Style("min-height", "3em") + Style("height", "2.25em") Style("margin-bottom", "1.25em") Style("gap", "0.75em") } @@ -2597,6 +2571,7 @@ private val SettingsScreen = FC { val On = Toggles[Entry.Id] ?: Entry.Default div { css(SettingsCheckboxRow) + Ui("CheckBoxComponentStyle-oneSetting") button { css(SettingsCheckbox(On)) onClick = { Toggles = Toggles + (Entry.Id to !On) } @@ -2613,22 +2588,23 @@ private val SettingsScreen = FC { val Value = Sliders[Entry.Id] ?: Entry.Default div { css(SettingsSliderWrap) + Ui("InputRangeComponentStyle-blockSoundVolume") div { css(SettingsSliderLabel) span { +Entry.Label } span { +"$Value%" } } - div { - css(SettingsSliderTrack) - div { css(SettingsSliderThumb(Value)) } - input { - css(SettingsSliderInput) - asDynamic()["type"] = "range" - asDynamic()["min"] = "0" - asDynamic()["max"] = "100" - asDynamic()["value"] = "$Value" - onChange = { E -> Sliders = Sliders + (Entry.Id to (E.target.value.toString().toIntOrNull() ?: Value)) } + input { + css { + Apply(SettingsRange) + Style("background", SettingsSliderGradient(Value)) } + Ui("SettingsComponentStyle-slider") + asDynamic()["type"] = "range" + asDynamic()["min"] = "0" + asDynamic()["max"] = "100" + asDynamic()["value"] = "$Value" + onChange = { E -> Sliders = Sliders + (Entry.Id to (E.target.value.toString().toIntOrNull() ?: Value)) } } } } diff --git a/TankiOffline/app/src/jsMain/resources/lobby3.css b/TankiOffline/app/src/jsMain/resources/lobby3.css index 4846017..a54d7bd 100644 --- a/TankiOffline/app/src/jsMain/resources/lobby3.css +++ b/TankiOffline/app/src/jsMain/resources/lobby3.css @@ -957,4 +957,31 @@ body { margin: 0; overflow: hidden; background: #001926; color: #fff; } [data-ui="settings.dropdown.list"]::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.3); border-radius: 0.2em; +} + +[data-ui="SettingsComponentStyle-slider"]::-webkit-slider-runnable-track { + width: 100%; + height: 0.375em; + background: transparent; +} +[data-ui="SettingsComponentStyle-slider"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 1.875em; + height: 1em; + border-radius: 0.25em; + background: #ffbc09; + margin-top: -0.3em; +} +[data-ui="SettingsComponentStyle-slider"]::-moz-range-track { + background: transparent; +} +[data-ui="SettingsComponentStyle-slider"]::-moz-range-progress { + background: #ffbc09; +} +[data-ui="SettingsComponentStyle-slider"]::-moz-range-thumb { + width: 1.875em; + height: 1em; + border: 0; + border-radius: 0.25em; + background: #ffbc09; } \ No newline at end of file