1.完成侧边栏和主体的过渡动画。

This commit is contained in:
amass 2023-06-19 17:50:24 +08:00
parent 74ce39fe73
commit 7c9c13f2a3
6 changed files with 49 additions and 35 deletions

View File

@ -18,7 +18,6 @@
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-redux": "^8.0.7",
"react-resize-detector": "^9.1.0",
"react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"sha1": "^1.1.1",

View File

@ -112,6 +112,8 @@ export default function () {
const accessToken = useSelector(state => state.user.accessToken);
const passportId = useSelector(state => state.user.passportId);
const currentTime = useSelector(state => state.recorder.currentTime);
const currentLyric = useSelector(state => state.recorder.currentLyric);
const [playerBarWidth, setPlayerBarWidth] = useState(0);
const [open, setOpen] = useState(true);
useEffect(() => {
yzs.get_record_list(accessToken, passportId).then(list => {
@ -126,17 +128,39 @@ export default function () {
const onClick = () => {
setOpen(!open);
setPlayerBarWidth(document.documentElement.clientWidth - 240 - 48); // 防止中途底部出现scrollbar
}
const handleResize = () => {
console.log("innerWidth", document.documentElement.clientWidth, document.documentElement.clientWidth - (open ? 240 : 0) - 48)
setPlayerBarWidth(document.documentElement.clientWidth - (open ? 240 : 0) - 48);
}
const onTransitionEnd = () => {
handleResize();
}
useEffect(() => {
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
useEffect(() => { handleResize(); }, [currentLyric]);
return <Box sx={{ display: 'flex' }}>
<ThemeProvider theme={theme}>
<CssBaseline />
<AppBar />
<RecordList open={open} fetchRecord={fetchRecord} />
<ClickHanlde open={open} onClick={onClick} />
<Main open={open}>
<PlayerBar currentTime={currentTime} />
<RecordLyrics currentTime={currentTime} />
<Main open={open}
onTransitionEnd={onTransitionEnd}
>
<PlayerBar width={playerBarWidth} currentTime={currentTime} />
<RecordLyrics currentLyric={currentLyric} currentTime={currentTime} />
</Main>
</ThemeProvider>
</Box >

View File

@ -1,8 +1,6 @@
import { MenuItem, Select, IconButton, Typography, Stack, Container } from "@mui/material"
import styles from './PlayerBar.module.css';
import { useSelector, useDispatch } from 'react-redux'
import { useEffect, useRef, useState, useCallback } from "react";
import { useResizeDetector } from 'react-resize-detector';
import pauseIcon from "./assets/play.png";
import playIcon from "./assets/pause.png";
import downloadIcon from "./assets/download.png";
@ -18,10 +16,9 @@ const durationFormat = (time) => {
return hour.toString().padStart(2, '0') + ":" + minute.toString().padStart(2, '0') + ":" + second.toString().padStart(2, '0');
}
export default function ({ currentTime }) {
export default function ({ width, currentTime }) {
const dispatch = useDispatch();
const [duration, setDuration] = useState(0); // 秒,有小数点
const [canvasWidth, setCanvasWidth] = useState(0);
const currentIndex = useSelector(state => state.recorder.currentIndex);
const recordList = useSelector(state => state.recorder.list);
const currentBlob = useSelector(state => state.recorder.currentBlob);
@ -49,14 +46,6 @@ export default function ({ currentTime }) {
dispatch(setCurrentTime(player.current.currentTime));
}
const onResize = useCallback((width, height) => {
setCanvasWidth(width - 90 - 70);
}, []);
const { ref: playerBar } = useResizeDetector({
onResize: onResize
});
const seekRecord = (second) => {
player.current.currentTime = second;
}
@ -81,23 +70,25 @@ export default function ({ currentTime }) {
</IconButton>
</Container>
<div className={styles.playerBar} ref={playerBar}>
<IconButton onClick={toggleState} sx={{ flexGrow: 1, width: 70, height: 70 }}>
<div style={{
display: "flex",
backgroundColor: "#E6EAEC",
height: "70px",
width: "100%",
}}>
<IconButton onClick={toggleState} sx={{ width: 70, height: 70 }}>
<img src={pause ? pauseIcon : playIcon} />
</IconButton>
<audio ref={player} src={currentBlob} onDurationChange={onDurationChange} onTimeUpdate={onTimeUpdate} />
<ProgressBar width={isNaN(canvasWidth) ? 0 : canvasWidth} duration={Math.ceil(duration * 1000)}
<ProgressBar width={isNaN(width) ? 0 : (width - 70 - 90)} duration={Math.ceil(duration * 1000)}
currentTime={currentTime} playing={!pause} seek={seekRecord}
waveData={currentWaveData}
/>
<Select
defaultValue={1.0}
onChange={onChange}
sx={{
flexGrow: 1,
width: 90
}}
sx={{ width: 90, height: 70 }}
>
<MenuItem value={0.5}>0.5X</MenuItem>
<MenuItem value={1.0}>1.0X</MenuItem>
@ -109,7 +100,6 @@ export default function ({ currentTime }) {
<Container maxWidth={false} sx={{ backgroundColor: "#F2F4F5" }}>
<Typography sx={{ color: "#6B7486" }}> {durationFormat(currentTime)} / {durationFormat(duration)}</Typography>
</Container>
</Stack>
}

View File

@ -13,7 +13,7 @@ import AccessTimeFilledIcon from '@mui/icons-material/AccessTimeFilled';
const drawerWidth = 240;
export default function ({ fetchRecord }) {
export default function ({ open, fetchRecord }) {
const dispatch = useDispatch();
const accessToken = useSelector(state => state.user.accessToken);
const currentIndex = useSelector(state => state.recorder.currentIndex);
@ -24,11 +24,16 @@ export default function ({ fetchRecord }) {
fetchRecord(accessToken, recordList.at(index));
}
return <Drawer
variant="permanent"
variant="persistent"
anchor="left"
open={open}
sx={{
width: drawerWidth,
flexShrink: 0,
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' },
'& .MuiDrawer-paper': {
width: drawerWidth,
boxSizing: 'border-box',
},
}}
>
<Toolbar variant="dense" />

View File

@ -10,12 +10,10 @@ function isHighlight(currentTime, { start, end }) {
export default function ({ currentTime }) {
const currentLyric = useSelector(state => state.recorder.currentLyric);
export default function ({ currentLyric, currentTime }) {
const currentIndex = useSelector(state => state.recorder.currentIndex);
const recordList = useSelector(state => state.recorder.list);
if (recordList.length === 0) return <React.Fragment />;
return <Paper className={styles.lyricsBrowser}>

View File

@ -153,8 +153,6 @@ export default function ({ width, duration, currentTime, playing, seek, waveData
width: width,
overflow: "scroll",
overflowY: "hidden",
// scrollBehavior: "smooth",
// overflowX: "hidden",
}}>
<div style={{
height: 60,
@ -164,10 +162,10 @@ export default function ({ width, duration, currentTime, playing, seek, waveData
left: width / 2 + 70,
margin: 0,
padding: 0,
}} />
<canvas ref={canvas} width={width + (duration / interval) * (pointWidth + pointMargin)} height={60}
<canvas ref={canvas}
height={60}
width={width + (duration / interval) * (pointWidth + pointMargin)}
/>
</div>
}