1.完成侧边栏和主体的过渡动画。
This commit is contained in:
parent
74ce39fe73
commit
7c9c13f2a3
@ -18,7 +18,6 @@
|
|||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^8.0.7",
|
"react-redux": "^8.0.7",
|
||||||
"react-resize-detector": "^9.1.0",
|
|
||||||
"react-router-dom": "^6.11.2",
|
"react-router-dom": "^6.11.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sha1": "^1.1.1",
|
"sha1": "^1.1.1",
|
||||||
|
@ -112,6 +112,8 @@ export default function () {
|
|||||||
const accessToken = useSelector(state => state.user.accessToken);
|
const accessToken = useSelector(state => state.user.accessToken);
|
||||||
const passportId = useSelector(state => state.user.passportId);
|
const passportId = useSelector(state => state.user.passportId);
|
||||||
const currentTime = useSelector(state => state.recorder.currentTime);
|
const currentTime = useSelector(state => state.recorder.currentTime);
|
||||||
|
const currentLyric = useSelector(state => state.recorder.currentLyric);
|
||||||
|
const [playerBarWidth, setPlayerBarWidth] = useState(0);
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
yzs.get_record_list(accessToken, passportId).then(list => {
|
yzs.get_record_list(accessToken, passportId).then(list => {
|
||||||
@ -126,17 +128,39 @@ export default function () {
|
|||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
setOpen(!open);
|
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' }}>
|
return <Box sx={{ display: 'flex' }}>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AppBar />
|
<AppBar />
|
||||||
<RecordList open={open} fetchRecord={fetchRecord} />
|
<RecordList open={open} fetchRecord={fetchRecord} />
|
||||||
<ClickHanlde open={open} onClick={onClick} />
|
<ClickHanlde open={open} onClick={onClick} />
|
||||||
<Main open={open}>
|
<Main open={open}
|
||||||
<PlayerBar currentTime={currentTime} />
|
onTransitionEnd={onTransitionEnd}
|
||||||
<RecordLyrics currentTime={currentTime} />
|
>
|
||||||
|
<PlayerBar width={playerBarWidth} currentTime={currentTime} />
|
||||||
|
<RecordLyrics currentLyric={currentLyric} currentTime={currentTime} />
|
||||||
</Main>
|
</Main>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</Box >
|
</Box >
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { MenuItem, Select, IconButton, Typography, Stack, Container } from "@mui/material"
|
import { MenuItem, Select, IconButton, Typography, Stack, Container } from "@mui/material"
|
||||||
import styles from './PlayerBar.module.css';
|
|
||||||
import { useSelector, useDispatch } from 'react-redux'
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
import { useEffect, useRef, useState, useCallback } from "react";
|
import { useEffect, useRef, useState, useCallback } from "react";
|
||||||
import { useResizeDetector } from 'react-resize-detector';
|
|
||||||
import pauseIcon from "./assets/play.png";
|
import pauseIcon from "./assets/play.png";
|
||||||
import playIcon from "./assets/pause.png";
|
import playIcon from "./assets/pause.png";
|
||||||
import downloadIcon from "./assets/download.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');
|
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 dispatch = useDispatch();
|
||||||
const [duration, setDuration] = useState(0); // 秒,有小数点
|
const [duration, setDuration] = useState(0); // 秒,有小数点
|
||||||
const [canvasWidth, setCanvasWidth] = useState(0);
|
|
||||||
const currentIndex = useSelector(state => state.recorder.currentIndex);
|
const currentIndex = useSelector(state => state.recorder.currentIndex);
|
||||||
const recordList = useSelector(state => state.recorder.list);
|
const recordList = useSelector(state => state.recorder.list);
|
||||||
const currentBlob = useSelector(state => state.recorder.currentBlob);
|
const currentBlob = useSelector(state => state.recorder.currentBlob);
|
||||||
@ -49,14 +46,6 @@ export default function ({ currentTime }) {
|
|||||||
dispatch(setCurrentTime(player.current.currentTime));
|
dispatch(setCurrentTime(player.current.currentTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
const onResize = useCallback((width, height) => {
|
|
||||||
setCanvasWidth(width - 90 - 70);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const { ref: playerBar } = useResizeDetector({
|
|
||||||
onResize: onResize
|
|
||||||
});
|
|
||||||
|
|
||||||
const seekRecord = (second) => {
|
const seekRecord = (second) => {
|
||||||
player.current.currentTime = second;
|
player.current.currentTime = second;
|
||||||
}
|
}
|
||||||
@ -81,23 +70,25 @@ export default function ({ currentTime }) {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
<div className={styles.playerBar} ref={playerBar}>
|
<div style={{
|
||||||
<IconButton onClick={toggleState} sx={{ flexGrow: 1, width: 70, height: 70 }}>
|
display: "flex",
|
||||||
|
backgroundColor: "#E6EAEC",
|
||||||
|
height: "70px",
|
||||||
|
width: "100%",
|
||||||
|
}}>
|
||||||
|
<IconButton onClick={toggleState} sx={{ width: 70, height: 70 }}>
|
||||||
<img src={pause ? pauseIcon : playIcon} />
|
<img src={pause ? pauseIcon : playIcon} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<audio ref={player} src={currentBlob} onDurationChange={onDurationChange} onTimeUpdate={onTimeUpdate} />
|
<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}
|
currentTime={currentTime} playing={!pause} seek={seekRecord}
|
||||||
waveData={currentWaveData}
|
waveData={currentWaveData}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={1.0}
|
defaultValue={1.0}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
sx={{
|
sx={{ width: 90, height: 70 }}
|
||||||
flexGrow: 1,
|
|
||||||
width: 90
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<MenuItem value={0.5}>0.5X</MenuItem>
|
<MenuItem value={0.5}>0.5X</MenuItem>
|
||||||
<MenuItem value={1.0}>1.0X</MenuItem>
|
<MenuItem value={1.0}>1.0X</MenuItem>
|
||||||
@ -109,7 +100,6 @@ export default function ({ currentTime }) {
|
|||||||
|
|
||||||
<Container maxWidth={false} sx={{ backgroundColor: "#F2F4F5" }}>
|
<Container maxWidth={false} sx={{ backgroundColor: "#F2F4F5" }}>
|
||||||
<Typography sx={{ color: "#6B7486" }}> {durationFormat(currentTime)} / {durationFormat(duration)}</Typography>
|
<Typography sx={{ color: "#6B7486" }}> {durationFormat(currentTime)} / {durationFormat(duration)}</Typography>
|
||||||
|
|
||||||
</Container>
|
</Container>
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ import AccessTimeFilledIcon from '@mui/icons-material/AccessTimeFilled';
|
|||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
|
|
||||||
export default function ({ fetchRecord }) {
|
export default function ({ open, fetchRecord }) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const accessToken = useSelector(state => state.user.accessToken);
|
const accessToken = useSelector(state => state.user.accessToken);
|
||||||
const currentIndex = useSelector(state => state.recorder.currentIndex);
|
const currentIndex = useSelector(state => state.recorder.currentIndex);
|
||||||
@ -24,11 +24,16 @@ export default function ({ fetchRecord }) {
|
|||||||
fetchRecord(accessToken, recordList.at(index));
|
fetchRecord(accessToken, recordList.at(index));
|
||||||
}
|
}
|
||||||
return <Drawer
|
return <Drawer
|
||||||
variant="permanent"
|
variant="persistent"
|
||||||
|
anchor="left"
|
||||||
|
open={open}
|
||||||
sx={{
|
sx={{
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' },
|
'& .MuiDrawer-paper': {
|
||||||
|
width: drawerWidth,
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Toolbar variant="dense" />
|
<Toolbar variant="dense" />
|
||||||
|
@ -10,12 +10,10 @@ function isHighlight(currentTime, { start, end }) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default function ({ currentTime }) {
|
export default function ({ currentLyric, currentTime }) {
|
||||||
const currentLyric = useSelector(state => state.recorder.currentLyric);
|
|
||||||
const currentIndex = useSelector(state => state.recorder.currentIndex);
|
const currentIndex = useSelector(state => state.recorder.currentIndex);
|
||||||
const recordList = useSelector(state => state.recorder.list);
|
const recordList = useSelector(state => state.recorder.list);
|
||||||
|
|
||||||
|
|
||||||
if (recordList.length === 0) return <React.Fragment />;
|
if (recordList.length === 0) return <React.Fragment />;
|
||||||
|
|
||||||
return <Paper className={styles.lyricsBrowser}>
|
return <Paper className={styles.lyricsBrowser}>
|
||||||
|
@ -153,8 +153,6 @@ export default function ({ width, duration, currentTime, playing, seek, waveData
|
|||||||
width: width,
|
width: width,
|
||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
overflowY: "hidden",
|
overflowY: "hidden",
|
||||||
// scrollBehavior: "smooth",
|
|
||||||
// overflowX: "hidden",
|
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
height: 60,
|
height: 60,
|
||||||
@ -164,10 +162,10 @@ export default function ({ width, duration, currentTime, playing, seek, waveData
|
|||||||
left: width / 2 + 70,
|
left: width / 2 + 70,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
padding: 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>
|
</div>
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user