feat: 沉浸模式底栏长度变化增加回弹动画

This commit is contained in:
JSR
2026-03-27 21:53:04 +08:00
parent 8ee3729596
commit 71862d996d
2 changed files with 37 additions and 5 deletions
+3 -2
View File
@@ -258,9 +258,10 @@ html.platform-macos #root {
opacity: 1; opacity: 1;
transform: translateX(-50%) translateY(0) scale(1); transform: translateX(-50%) translateY(0) scale(1);
transition: transition:
width 420ms cubic-bezier(0.2, 1.2, 0.26, 1),
opacity 200ms ease, opacity 200ms ease,
transform 260ms cubic-bezier(0.22, 1, 0.36, 1); transform 320ms cubic-bezier(0.2, 1.2, 0.26, 1);
will-change: opacity, transform; will-change: width, opacity, transform;
} }
.ss-immersive-toolbar.is-hidden { .ss-immersive-toolbar.is-hidden {
+34 -3
View File
@@ -118,6 +118,8 @@ export const Home: React.FC<HomeProps> = ({
const groupRefs = useRef<Record<string, HTMLDivElement | null>>({}) const groupRefs = useRef<Record<string, HTMLDivElement | null>>({})
const searchAreaRef = useRef<HTMLDivElement>(null) const searchAreaRef = useRef<HTMLDivElement>(null)
const immersiveToolbarRef = useRef<HTMLDivElement>(null) const immersiveToolbarRef = useRef<HTMLDivElement>(null)
const immersiveToolbarContentRef = useRef<HTMLDivElement>(null)
const [immersiveToolbarWidth, setImmersiveToolbarWidth] = useState<number | null>(null)
const [selectedStudent, setSelectedStudent] = useState<student | null>(null) const [selectedStudent, setSelectedStudent] = useState<student | null>(null)
const [batchMode, setBatchMode] = useState(false) const [batchMode, setBatchMode] = useState(false)
@@ -321,6 +323,33 @@ export const Home: React.FC<HomeProps> = ({
return () => document.removeEventListener("mousedown", onDocumentClick) return () => document.removeEventListener("mousedown", onDocumentClick)
}, []) }, [])
useEffect(() => {
if (!immersiveMode) return
const contentEl = immersiveToolbarContentRef.current
if (!contentEl) return
let frameId: number | null = null
const updateToolbarWidth = () => {
if (frameId !== null) cancelAnimationFrame(frameId)
frameId = requestAnimationFrame(() => {
const contentWidth = Math.ceil(contentEl.getBoundingClientRect().width)
const nextWidth = contentWidth + 20
setImmersiveToolbarWidth((prev) => (prev === nextWidth ? prev : nextWidth))
})
}
updateToolbarWidth()
const observer = new ResizeObserver(updateToolbarWidth)
observer.observe(contentEl)
window.addEventListener("resize", updateToolbarWidth)
return () => {
observer.disconnect()
window.removeEventListener("resize", updateToolbarWidth)
if (frameId !== null) cancelAnimationFrame(frameId)
}
}, [immersiveMode])
useEffect(() => { useEffect(() => {
return () => { return () => {
if (longPressTimerRef.current !== null) { if (longPressTimerRef.current !== null) {
@@ -2481,9 +2510,8 @@ export const Home: React.FC<HomeProps> = ({
position: "fixed", position: "fixed",
left: "50%", left: "50%",
bottom: isPortraitMode ? "12px" : "16px", bottom: isPortraitMode ? "12px" : "16px",
transform: "translateX(-50%)",
zIndex: 1100, zIndex: 1100,
width: "max-content", width: immersiveToolbarWidth ? `${immersiveToolbarWidth}px` : "max-content",
maxWidth: "calc(100vw - 20px)", maxWidth: "calc(100vw - 20px)",
borderRadius: "999px", borderRadius: "999px",
border: "1px solid color-mix(in srgb, var(--ss-border-color) 80%, transparent)", border: "1px solid color-mix(in srgb, var(--ss-border-color) 80%, transparent)",
@@ -2497,7 +2525,10 @@ export const Home: React.FC<HomeProps> = ({
}} }}
> >
<div <div
ref={searchAreaRef} ref={(node) => {
searchAreaRef.current = node
immersiveToolbarContentRef.current = node
}}
style={{ style={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",