[英]How to make AppBar component from material-ui-next react to scroll events
As per Material Design guidelines :根据材料设计指南:
Upon scrolling, the top app bar can […] transform in the following ways:
滚动后,顶部应用栏可以 [...] 以下列方式转换:
- Scrolling upward hides the top app bar- 向上滚动隐藏顶部应用栏
- Scrolling downward reveals the top app bar- 向下滚动显示顶部应用栏
When the top app bar scrolls, its elevation above other elements becomes apparent.当顶部应用栏滚动时,它在其他元素之上的高度变得明显。
Is there any built-in approach to do this in material-ui-next or should it be considered as a new feature?在 material-ui-next 中是否有任何内置方法可以做到这一点,还是应该将其视为新功能? Can you give a hint on how to achieve the animation of the AppBar component as described in the guidelines?
能否给出指南中描述的如何实现 AppBar 组件动画的提示?
To my knowledge, there's no out-of-the-box solution for this at the moment.据我所知,目前没有现成的解决方案。 It's quite easy to implement though.
不过它很容易实现。 Here is a snippet that subscribes to scroll events and hides or shows the AppBar accordingly:
这是订阅滚动事件并相应地隐藏或显示 AppBar 的片段:
const styles = {
root: {
flexGrow: 1,
},
show: {
transform: 'translateY(0)',
transition: 'transform .5s',
},
hide: {
transform: 'translateY(-110%)',
transition: 'transform .5s',
},
};
class CollapsibleAppBar extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
shouldShow: null,
};
this.lastScroll = null;
this.handleScroll = this.handleScroll.bind(this);
// Alternatively, you can throttle scroll events to avoid
// updating the state too often. Here using lodash.
// this.handleScroll = _.throttle(this.handleScroll.bind(this), 100);
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll, { passive: true });
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
handleScroll(evt) {
const lastScroll = window.scrollY;
if (lastScroll === this.lastScroll) {
return;
}
const shouldShow = (this.lastScroll !== null) ? (lastScroll < this.lastScroll) : null;
if (shouldShow !== this.state.shouldShow) {
this.setState((prevState, props) => ({
...prevState,
shouldShow,
}));
}
this.lastScroll = lastScroll;
}
render() {
const { classes } = this.props;
return (
<AppBar
position="fixed"
color="default"
className={
`${classes.root} ${
this.state.shouldShow === null ? '' : (
this.state.shouldShow ? classes.show : classes.hide
)
}`
}
>
<Toolbar>
<Typography variant="title" color="inherit">
Title
</Typography>
</Toolbar>
</AppBar>
);
}
}
CollapsibleAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(CollapsibleAppBar);
in the current version of Material-ui, you can simply use the following在当前版本的 Material-ui 中,您可以简单地使用以下内容
import clsx from "clsx";
import useScrollTrigger from "@material-ui/core/useScrollTrigger";
const trigger = useScrollTrigger();
<AppBar className={trigger ? classes.show : classes.hide}>
</AppBar>
https://material-ui.com/components/app-bar/#usescrolltrigger-options-trigger https://material-ui.com/components/app-bar/#usescrolltrigger-options-trigger
对于那些仍在寻找内置功能的人,可以在material-ui
找到滚动时隐藏应用栏。
this seem to work for me这似乎对我有用
import {
useScrollTrigger,
Fab,
Zoom,
} from '@mui/material';
... ...
function ElevationScroll(props) {
const { children } = props;
const theme = useTheme();
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
});
return React.cloneElement(children, {
sx: trigger
? {
bgcolor: theme.palette.primary.dark,
'transition-duration': '500ms',
'transition-property':
'padding-top, padding-bottom, background-color',
'transition-timing-function': 'ease-in-out',
}
: {
pt: 2,
pb: 2,
bgcolor: theme.palette.primary.main,
},
elevation: trigger ? 5 : 0,
});
}
function ScrollTop(props) {
const { children } = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 200,
});
const handleClick = (event) => {
const anchor = (event.target.ownerDocument || document).querySelector(
'#back-to-top-anchor'
);
if (anchor) {
anchor.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}
};
return (
<Zoom in={trigger}>
<Box
onClick={handleClick}
role="presentation"
sx={{ position: 'fixed', bottom: 16, right: 16, zIndex: 1 }}
>
{children}
</Box>
</Zoom>
);
}
... ...
return (
<React.Fragment>
<ElevationScroll {...props}>
<AppBar position="sticky">
...
</AppBar>
</ElevationScroll>
<Toolbar
id="back-to-top-anchor"
className="_Toolbar"
sx={{
minHeight: '0 !important',
}}
/>
<ScrollTop {...props}>
<Fab color="secondary" size="small" aria-label="scroll back to top">
<KeyboardArrowUpIcon />
</Fab>
</ScrollTop>
</React.Fragment>
this seem to work for me这似乎对我有用
import {
useScrollTrigger,
Fab,
Zoom,
} from '@mui/material';
... ...
function ElevationScroll(props) {
const { children } = props;
const theme = useTheme();
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
});
return React.cloneElement(children, {
sx: trigger
? {
bgcolor: theme.palette.primary.dark,
'transition-duration': '500ms',
'transition-property':
'padding-top, padding-bottom, background-color',
'transition-timing-function': 'ease-in-out',
}
: {
pt: 2,
pb: 2,
bgcolor: theme.palette.primary.main,
},
elevation: trigger ? 5 : 0,
});
}
function ScrollTop(props) {
const { children } = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 200,
});
const handleClick = (event) => {
const anchor = (event.target.ownerDocument || document).querySelector(
'#back-to-top-anchor'
);
if (anchor) {
anchor.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}
};
return (
<Zoom in={trigger}>
<Box
onClick={handleClick}
role="presentation"
sx={{ position: 'fixed', bottom: 16, right: 16, zIndex: 1 }}
>
{children}
</Box>
</Zoom>
);
}
... ...
return (
<React.Fragment>
<ElevationScroll {...props}>
<AppBar position="sticky">
...
</AppBar>
</ElevationScroll>
<Toolbar
id="back-to-top-anchor"
className="_Toolbar"
sx={{
minHeight: '0 !important',
}}
/>
<ScrollTop {...props}>
<Fab color="secondary" size="small" aria-label="scroll back to top">
<KeyboardArrowUpIcon />
</Fab>
</ScrollTop>
</React.Fragment>
https://mui.com/components/app-bar/#usescrolltrigger-options-trigger https://mui.com/components/app-bar/#usescrolltrigger-options-trigger
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.