feat(slider): 添加仅可拖动滑块的自定义音量滑块组件
- 新增 ThumbOnlyRangeSlider 组件,禁用轨道点击,仅支持滑块拖动 - 避免触摸时点击轨道导致音量跳变问题 - 在 Home 页面替换旧的音量输入滑块为新组件 - 移除旧音量滑块相关多余的引用和函数 - 支持拖动开始、结束和释放回调以优化操作逻辑 - 优化了 BrandDrawer 组件的样式以支持不同单位的视口高度显示
This commit is contained in:
+12
-64
@@ -12,6 +12,7 @@
|
||||
import { useDevice } from "@/contexts/DeviceContext";
|
||||
import ConnectionPlaceholder from "@/components/ConnectionPlaceholder";
|
||||
import BottomNav from "@/components/BottomNav";
|
||||
import ThumbOnlyRangeSlider from "@/components/ThumbOnlyRangeSlider";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -231,8 +232,6 @@ export default function Home() {
|
||||
|
||||
const [localVol, setLocalVol] = useState(deviceState?.volume ?? 100);
|
||||
const isDragging = useRef(false);
|
||||
const volumeSliderRef = useRef<HTMLInputElement>(null);
|
||||
const volumeSliderDragAllowedRef = useRef(false);
|
||||
const knobDraggingRef = useRef(false);
|
||||
const knobActivePointerIdRef = useRef<number | null>(null);
|
||||
const knobStartAngleRef = useRef(0);
|
||||
@@ -249,16 +248,6 @@ export default function Home() {
|
||||
knobLastVolRef.current = localVol;
|
||||
}, [localVol]);
|
||||
|
||||
const isPointerOnVolumeSliderThumb = useCallback((clientX: number) => {
|
||||
const el = volumeSliderRef.current;
|
||||
if (!el) return false;
|
||||
const rect = el.getBoundingClientRect();
|
||||
if (rect.width <= 0) return false;
|
||||
const thumbCenterX = rect.left + (localVol / 200) * rect.width;
|
||||
const hitRadius = Math.max(28, rect.width * 0.05);
|
||||
return Math.abs(clientX - thumbCenterX) <= hitRadius;
|
||||
}, [localVol]);
|
||||
|
||||
const handlePowerOff = useCallback(async () => {
|
||||
if (powerActionRef.current) return;
|
||||
powerActionRef.current = true;
|
||||
@@ -677,67 +666,26 @@ export default function Home() {
|
||||
background: "#00FFF6",
|
||||
boxShadow: "0 0 8px rgba(0,255,246,0.5)"
|
||||
}} />
|
||||
<input
|
||||
ref={volumeSliderRef}
|
||||
type="range" min={0} max={200} value={localVol}
|
||||
<ThumbOnlyRangeSlider
|
||||
min={0}
|
||||
max={200}
|
||||
value={localVol}
|
||||
disabled={volumePassthroughActive}
|
||||
className="cyan-slider cyan-slider-thumb-only relative z-10 disabled:opacity-50"
|
||||
onChange={(e) => {
|
||||
className={volumePassthroughActive ? "opacity-50" : undefined}
|
||||
onChange={(v) => {
|
||||
if (volumePassthroughActive) return;
|
||||
if (!volumeSliderDragAllowedRef.current) {
|
||||
e.target.value = String(localVol);
|
||||
return;
|
||||
}
|
||||
const v = Number(e.target.value);
|
||||
setLocalVol(v);
|
||||
}}
|
||||
onPointerDown={(e) => {
|
||||
onDragStart={() => {
|
||||
if (volumePassthroughActive) return;
|
||||
const onThumb = isPointerOnVolumeSliderThumb(e.clientX);
|
||||
volumeSliderDragAllowedRef.current = onThumb;
|
||||
if (!onThumb) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
isDragging.current = true;
|
||||
}}
|
||||
onPointerUp={(e) => {
|
||||
const allowed = volumeSliderDragAllowedRef.current;
|
||||
volumeSliderDragAllowedRef.current = false;
|
||||
onDragEnd={() => {
|
||||
isDragging.current = false;
|
||||
if (!allowed || volumePassthroughActive) return;
|
||||
applyVolume(Number(e.currentTarget.value));
|
||||
}}
|
||||
onPointerCancel={(e) => {
|
||||
const allowed = volumeSliderDragAllowedRef.current;
|
||||
volumeSliderDragAllowedRef.current = false;
|
||||
isDragging.current = false;
|
||||
if (!volumePassthroughActive && allowed) {
|
||||
applyVolume(Number(e.currentTarget.value));
|
||||
}
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
const allowed = volumeSliderDragAllowedRef.current;
|
||||
volumeSliderDragAllowedRef.current = false;
|
||||
isDragging.current = false;
|
||||
if (!volumePassthroughActive && allowed) {
|
||||
applyVolume(Number(e.currentTarget.value));
|
||||
}
|
||||
}}
|
||||
onKeyUp={(e) => {
|
||||
const k = e.key;
|
||||
if (
|
||||
k === "ArrowLeft" ||
|
||||
k === "ArrowRight" ||
|
||||
k === "ArrowUp" ||
|
||||
k === "ArrowDown" ||
|
||||
k === "Home" ||
|
||||
k === "End" ||
|
||||
k === "PageUp" ||
|
||||
k === "PageDown"
|
||||
) {
|
||||
applyVolume(Number(e.currentTarget.value));
|
||||
}
|
||||
onRelease={(v) => {
|
||||
if (volumePassthroughActive) return;
|
||||
applyVolume(v);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user