The react-swipeable-views library is providing example usages. I want to reuse the coverflow example, but in a react functional comp. way. I almost managed to get it working. However on my implementation, the swipeable element can get stuck during swipe, if you swipe slowly (the scale is not applied anymore). See screenshot:
In the demo of react-swipeable views this is somehow not happening. This example is using react-spring for the animation transitions. I provided a stackblitz demo that is reproducable and maybe you can find out the issue.
component
const useStyles = makeStyles((theme) => ({
root: {
background: theme.palette.background.paper,
padding: theme.spacing(0, 6),
},
img: {
width: 180,
height: 180,
display: "block",
marginBottom: theme.spacing(2),
},
container: {
padding: theme.spacing(2),
borderRadius: 4,
justifyContent: "center",
maxWidth: 320,
margin: "auto",
},
slide: {
padding: theme.spacing(3, 2),
color: theme.palette.text.primary,
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
display: "flex",
},
}));
const albums = [
{
name: "Abbey Road",
src: "https://picsum.photos/200/300",
},
{
name: "Bat Out of Hell",
src: "https://picsum.photos/200/300",
},
{
name: "Homogenic",
src: "https://picsum.photos/200/300",
},
{
name: "Number of the Beast",
src: "https://picsum.photos/200/300",
},
{
name: "It's Blitz",
src: "https://picsum.photos/200/300",
},
{
name: "The Man-Machine",
src: "https://picsum.photos/200/300",
},
];
export function StatisticSelector() {
const classes = useStyles();
const [index, setIndex] = useState(0);
const [props, start] = useSpring(() => ({
from: { position: 0 },
}));
function handleChangeIndex(indexNum) {
setIndex(indexNum);
}
function handleSwitch(index, type) {
if (type === "end") {
start({
from: { position: props.position.value },
to: { position: Math.round(index) },
});
return;
}
props.position.setValue(index);
}
function interpolatePositionProps(range, output) {
return props.position.interpolate({
range,
output,
});
}
return (
<div className={classes.container}>
<SwipeableViews
index={index}
className={classes.root}
onChangeIndex={handleChangeIndex}
onSwitching={handleSwitch}
enableMouseEvents
>
{albums.map((album, currentIndex) => {
const inputRange = albums.map((_, i) => i);
const scale = interpolatePositionProps(
inputRange,
inputRange.map((i) => (currentIndex === i ? 1 : 0.7))
).interpolate((x) => `scale(${x})`);
const opacity = interpolatePositionProps(
inputRange,
inputRange.map((i) => (currentIndex === i ? 1 : 0.3))
);
const translateX = interpolatePositionProps(
inputRange,
inputRange.map((i) => (100 / 2) * (i - currentIndex))
).interpolate((x) => `translateX(${x}px)`);
const scaleAndTranslateX = interpolate(
[scale, translateX],
(scale, translateX) => `${scale} ${translateX}`
);
return (
<animated.div
key={String(currentIndex)}
className={classes.slide}
style={Object.assign({
opacity,
transform: scaleAndTranslateX,
})}
>
<img className={classes.img} src={album.src} alt="cover" />
<Button variant="contained" color="primary" size="small">
Select
</Button>
</animated.div>
);
})}
</SwipeableViews>
</div>
);
}
from react-scpring clean scale and translateX transition
No comments:
Post a Comment