.container {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 90vh;
width: 100%;
}
.center {
align-self: center;
}
.top-left {
align-self: flex-start;
}
.bot-right {
align-self: flex-end;
}
.image {
width: 150px;
height: 130px;
}
.flip {
transform: rotate(0.5turn);
}
.force-moveX {
transition: transform 1s;
transform: translate(0, 0) !important;
}
.force-moveY {
transition: transform 1s;
transition-delay: 1s;
transform: translateY(0) !important;
}
const FarmFig = ({ image, handleClick = null, setRef, locs, animClass }) => {
return (
<div
className={`${animClass}X`}
style={{
transform: `translate(${locs[1]}px`,
}}
>
<div
className={`${animClass}Y`}
style={{
transform: `translateY(${locs[0]}px)`,
}}
>
<img
className={`image ${animClass}`}
src={image}
ref={setRef}
onClick={handleClick}
/>
</div>
</div>
);
};
class App extends React.Component {
constructor() {
super();
this.center = React.createRef();
this.state = {
images: {
tl:
"https://lh3.googleusercontent.com/proxy/4CqxhghbTJ5NP49WTvdRtMRdR1DqiAVYesY0MvqqwmaGl_Vq9uwFhxKHb_Zh4pmzPIq8g5WkZmzD1ja3k_fc_DSDTZejwvE",
c:
"https://lh3.googleusercontent.com/proxy/Erix2ztSUVwc7gKZLH5i9T2gCWLhEuxF-Ix2J0Dfdx1hJpjQBBsQOgcrgIlxAu5D9L_zMHGykyFLhFx-10eZYVzzE_PK7Zg",
br:
"https://pngarchive.com/public/uploads/small/11559054782q4dsokodad1svijk1zzlyrjdwtmlygkkaxxvooeqevdyrbomu3b5vwcwst0ndcidr89gdf0nyleyffoncphgazeqmnpmdubfypow.png",
},
animate: true,
transition: {
center: {
startTop: 0,
startRight: 0,
},
corner: {
farmItem: null,
startTop: 0,
startRight: 0,
},
},
};
}
//find locatin of center image
getCenterLoc = () => {
const imageEndTop =
this.center.current.getBoundingClientRect().top +
document.documentElement.scrollTop;
const imageEndRight =
this.center.current.getBoundingClientRect().right +
document.documentElement.scrollLeft;
return [imageEndTop, imageEndRight];
};
handleClick = ({ target }) => {
// find location of clicked image
const imageStartTop =
target.getBoundingClientRect().top + document.documentElement.scrollTop;
const imageStartRight =
target.getBoundingClientRect().right +
document.documentElement.scrollLeft;
//find ending location of clicked image
let endLoc = this.getCenterLoc();
let selectedImage;
this.setState((prevState) => {
//switch clicked image with the center image
if (prevState.images.tl === target.src) {
selectedImage = "tl";
prevState.images.tl = prevState.images.c;
prevState.images.c = target.src;
} else {
selectedImage = "br";
prevState.images.br = prevState.images.c;
prevState.images.c = target.src;
}
return {
images: prevState.images,
animate: false,
transition: {
center: {
startTop: imageStartTop - endLoc[0],
startRight: imageStartRight - endLoc[1],
},
corner: {
farmItem: selectedImage,
startTop: endLoc[0] - imageStartTop,
startRight: endLoc[1] - imageStartRight,
},
},
};
});
setTimeout(() => this.triggerAnim(), 200);
};
triggerAnim = () => {
this.setState({ animate: true });
};
getOldLoc = (loc) => {
const { corner } = this.state.transition;
let top, right;
if (corner.farmItem === loc) {
top = corner.startTop;
right = corner.startRight;
} else {
top = 0;
right = 0;
}
return [top, right];
};
render() {
const { tl, c, br } = this.state.images;
const { center } = this.state.transition;
const animClass = this.state.animate ? "force-move" : "";
return (
<div
className="container"
onClick={(e) => console.log(e.clientX, e.clientY)}
>
<div className="top-left">
<FarmFig
image={tl}
handleClick={this.handleClick}
locs={this.getOldLoc("tl")}
animClass={animClass}
/>
</div>
<div className="center">
<FarmFig
image={c}
setRef={this.center}
locs={[center.startTop, center.startRight]}
animClass={animClass}
/>
</div>
<div className="bot-right">
<FarmFig
image={br}
handleClick={this.handleClick}
locs={this.getOldLoc("br")}
animClass={animClass}
/>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
View Compiled