feat: 右上角图标改造为手势状态指示器
- 默认灰色「探索」罗盘图标(Compass) - 识别到手势(dpm:gesture)→ 变绿色「惊喜」表情(EmojiSurprised)+ 光晕脉冲,3s 后恢复 - title 同步切换(关于 PineSound / 识别到手势),点击仍打开关于弹窗 - 新增 explore/surprise 图标映射与手势状态样式
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
||||
Volume, VolumeOff, ChevronLeft, ChevronRight, PlayerPlay, PlayerPause,
|
||||
Send, Trash, Eraser, Headset, CircleDot, AlertCircle,
|
||||
Microphone, MicrophoneFilled, MicrophoneOff, MessageCircle,
|
||||
Camera, CameraOff, HandStop, Copyright,
|
||||
Camera, CameraOff, HandStop, Copyright, Compass, EmojiSurprised,
|
||||
} from '@appica/icons-react';
|
||||
|
||||
/* 名称 → 图标组件映射(推荐的调用方式:icon="bolt") */
|
||||
@@ -90,6 +90,8 @@ const NAME_MAP = {
|
||||
'camera-off': CameraOff,
|
||||
'hand-stop': HandStop,
|
||||
copyright: Copyright,
|
||||
explore: Compass,
|
||||
surprise: EmojiSurprised,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -124,5 +126,5 @@ export {
|
||||
Volume, VolumeOff, ChevronLeft, ChevronRight, PlayerPlay, PlayerPause,
|
||||
Send, Trash, Eraser, Headset, CircleDot, AlertCircle,
|
||||
Microphone, MicrophoneFilled, MicrophoneOff, MessageCircle,
|
||||
Camera, CameraOff, HandStop, Copyright,
|
||||
Camera, CameraOff, HandStop, Copyright, Compass, EmojiSurprised,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import Icon from './Icons';
|
||||
import MediaHeaderControls from './MediaHeaderControls';
|
||||
@@ -23,13 +23,30 @@ export default function PageHeader() {
|
||||
const location = useLocation();
|
||||
const [now, setNow] = useState(new Date());
|
||||
const [aboutOpen, setAboutOpen] = useState(false);
|
||||
const [gestureHit, setGestureHit] = useState(false); // 识别到手势 → 惊喜图标 3s
|
||||
const pageIdx = usePageIndex();
|
||||
const gestureTimer = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const iv = setInterval(() => setNow(new Date()), 1000);
|
||||
return () => clearInterval(iv);
|
||||
}, []);
|
||||
|
||||
// 全局手势事件 → 右上角状态图标(默认灰色探索 → 识别到手势变绿色惊喜)
|
||||
useEffect(() => {
|
||||
const onGesture = (e) => {
|
||||
if (!e.detail || !e.detail.type) return;
|
||||
setGestureHit(true);
|
||||
if (gestureTimer.current) clearTimeout(gestureTimer.current);
|
||||
gestureTimer.current = setTimeout(() => setGestureHit(false), 3000);
|
||||
};
|
||||
window.addEventListener('dpm:gesture', onGesture);
|
||||
return () => {
|
||||
window.removeEventListener('dpm:gesture', onGesture);
|
||||
if (gestureTimer.current) clearTimeout(gestureTimer.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
||||
const week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
|
||||
const timeStr = now.toLocaleTimeString('zh-CN', { hour12: false });
|
||||
@@ -84,13 +101,13 @@ export default function PageHeader() {
|
||||
{status}
|
||||
</div>
|
||||
<button
|
||||
className="bd-about-btn"
|
||||
className={`bd-about-btn${gestureHit ? ' gesture-hit' : ''}`}
|
||||
type="button"
|
||||
title="关于 PineSound"
|
||||
title={gestureHit ? '识别到手势' : '关于 PineSound'}
|
||||
aria-label="关于 PineSound"
|
||||
onClick={() => setAboutOpen(true)}
|
||||
>
|
||||
<Icon name="info" size={14} />
|
||||
<Icon name={gestureHit ? 'surprise' : 'explore'} size={15} />
|
||||
</button>
|
||||
<div className="bd-clock">
|
||||
<div className="bd-clock-time">{timeStr}</div>
|
||||
|
||||
@@ -2587,6 +2587,18 @@
|
||||
border-color: #2f6bff;
|
||||
background: #fff;
|
||||
}
|
||||
/* 手势状态:识别到手势 → 绿色惊喜图标 + 光晕脉冲 */
|
||||
.bd-about-btn.gesture-hit {
|
||||
color: var(--bd-green, #17b26a);
|
||||
border-color: rgba(23, 178, 106, 0.55);
|
||||
background: rgba(23, 178, 106, 0.1);
|
||||
box-shadow: 0 0 14px rgba(23, 178, 106, 0.45);
|
||||
animation: bdGesturePulse 1s ease-in-out infinite;
|
||||
}
|
||||
@keyframes bdGesturePulse {
|
||||
0%, 100% { box-shadow: 0 0 8px rgba(23, 178, 106, 0.3); transform: scale(1); }
|
||||
50% { box-shadow: 0 0 18px rgba(23, 178, 106, 0.6); transform: scale(1.08); }
|
||||
}
|
||||
|
||||
.about-overlay {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user