V1.3.8: 均衡器频段改横向滑杆 + 遥控确认键调节/退出 + 触控需按住滑块
1) 频段 UI 改为横向滑动条
删除 VerticalEqBar, 新增自绘控件 EqSlider(横向), 音量与频段共用:
每个频段一行「频率 | 滑杆 | 增益(dB)」, 带 0dB 参考线并从参考线填充到当前值。
弹窗布局随之改为: 音量横向杆 → 均衡器开关 → 预设 → 5 行频段滑杆。
2) 电视遥控交互(按确认键才可调节控件点, 同理按确认键退出控制)
- 焦点在滑杆上时方向键**不**改数值(先让焦点在控件间正常移动);
- 按确认键进入「调节态」(描边变亮变粗), 此时左右/上下键才调值;
- 再按确认键退出调节态; 调节态下 BACK 也只退出调节态、不关弹窗; 失焦自动退出。
新增 onInteractionFinished 回调, 退出调节态/抬手/失焦时统一 applyPlaybackMode +
saveState(音量) 或 applyEqualizerSettings(频段), 避免逐步落盘。
3) 触控优化(含远程控制): 必须按住控件点(滑块)才能滑动
- App: EqSlider 触摸按下时先做 hitsThumb 命中判断(容差 26dp, 含纵向范围),
未命中直接不处理 -> 点轨道空白不会跳变数值;
- 远程点歌页面: 新增 attachThumbOnlyDrag(), 对 input[type=range] 的
pointerdown/touchstart/mousedown 做同样的滑块命中判断, 未命中则 preventDefault,
命中才放行浏览器原生拖动; 滑块光标改 grab/grabbing 提示可拖。
4) 自适应随之调整: 预算按「频段行数」均分得到行高(clamp 38~56dp),
两遍 fit 超出时收缩的是频段行高(下限 34dp), 文字行仍全部 wrap_content。
版本号 1.3.7 -> 1.3.8(versionCode 13 -> 14)。按约定本次不发布 Release, 仅本地打包测试。
This commit is contained in:
@@ -111,6 +111,7 @@ function renderEqualizer(eq) {
|
||||
bands.forEach((band, index) => {
|
||||
const input = $("#eqBand" + index);
|
||||
if (!input) return;
|
||||
attachThumbOnlyDrag(input);
|
||||
input.addEventListener("input", () => {
|
||||
const value = $("#eqValue" + index);
|
||||
if (value) value.textContent = Number(input.value).toFixed(1);
|
||||
@@ -143,6 +144,40 @@ function currentEqLevels() {
|
||||
return Array.from($$("#eqBands input[type=range]")).map((input) => Number(input.value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 触控优化:滑块必须按住「控件点(滑块)」才能拖动,点轨道空白处不跳变数值。
|
||||
*
|
||||
* `<input type="range">` 默认点轨道任意位置都会跳值并开始拖动;这里在指针按下时先做
|
||||
* 命中判断 —— 命中滑块才放行浏览器原生拖动,否则 preventDefault 拦掉这次手势。
|
||||
* 只有粘性标记滑块处于按下状态时才放行,手指移出轨道仍可继续拖动(由原生处理)。
|
||||
*/
|
||||
function attachThumbOnlyDrag(input) {
|
||||
if (!input || input.dataset.thumbOnly === "1") return;
|
||||
input.dataset.thumbOnly = "1";
|
||||
const blocked = (event) => {
|
||||
const rect = input.getBoundingClientRect();
|
||||
const point = event.touches && event.touches.length ? event.touches[0] : event;
|
||||
const x = point.clientX;
|
||||
const y = point.clientY;
|
||||
// 粗略还原轨道几何:控件左右各留半个滑块宽度。
|
||||
const thumb = 22;
|
||||
const trackLeft = rect.left + thumb / 2;
|
||||
const trackRight = rect.right - thumb / 2;
|
||||
const span = trackRight - trackLeft;
|
||||
if (span <= 0 || y < rect.top - thumb || y > rect.bottom + thumb) return true;
|
||||
const min = Number(input.min || 0);
|
||||
const max = Number(input.max || 100);
|
||||
const ratio = (Number(input.value) - min) / (max - min || 1);
|
||||
const thumbX = trackLeft + ratio * span;
|
||||
// 命中滑块(含手指触控容差)→ 放行拖动;否则拦掉,避免点轨道跳值。
|
||||
return Math.abs(x - thumbX) > Math.max(thumb, 26);
|
||||
};
|
||||
const guard = (event) => { if (blocked(event)) event.preventDefault(); };
|
||||
input.addEventListener("pointerdown", guard, { passive: false });
|
||||
input.addEventListener("touchstart", guard, { passive: false });
|
||||
input.addEventListener("mousedown", guard);
|
||||
}
|
||||
|
||||
async function updateEqualizer(values) {
|
||||
try {
|
||||
await api("/api/v1/player/equalizer", { method: "PATCH", body: JSON.stringify(values) });
|
||||
@@ -270,6 +305,7 @@ $("#more").addEventListener("click", () => search(false));
|
||||
$("#hotPrev").addEventListener("click", () => loadHot(uiState.hotPage - 1));
|
||||
$("#hotNext").addEventListener("click", () => loadHot(uiState.hotPage + 1));
|
||||
// 音乐音量可调; 麦克风音量由功放硬件控制, 不再向设备发送无效果请求。
|
||||
attachThumbOnlyDrag($("#musicVolume"));
|
||||
$("#musicVolume").addEventListener("input", (event) => { $("#musicValue").textContent = event.target.value; });
|
||||
$("#musicVolume").addEventListener("change", (event) => updateAudio({ musicVolume: Number(event.target.value) }));
|
||||
// 均衡器入口(与设备端弹窗等价): 开关 / 恢复标准
|
||||
|
||||
Reference in New Issue
Block a user