A Pen by jose-developer on CodePen.
Last active
March 27, 2020 00:17
-
-
Save gaygenius/a7feee1378df25e7497d7b938423033e to your computer and use it in GitHub Desktop.
Move object with buttons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="container"></div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
console.clear(); | |
const PositionedObject = ({ x, y, objectDimensionPx, children }) => { | |
return ( | |
<div | |
style={{ | |
position: "relative", | |
left: x, | |
top: y, | |
maxWidth: `${objectDimensionPx}px` | |
}} | |
> | |
{children} | |
</div> | |
); | |
}; | |
const PositionedObjectContainer = ({ | |
perimeterDimensionPx, | |
moveButtonWidthPx, | |
moveDimensionPx, | |
objectDimensionPx, | |
children | |
}) => { | |
const initialPosition = (perimeterDimensionPx - objectDimensionPx) / 2; | |
const [x, setX] = React.useState(initialPosition); | |
const [y, setY] = React.useState(initialPosition); | |
const [activeButton, setActiveButton] = React.useState(null); | |
const moveActions = { | |
reset: function () { | |
setX(initialPosition); | |
setY(initialPosition); | |
}, | |
up: function () { | |
setY(Math.max(0, y - moveDimensionPx)); | |
}, | |
left: function () { | |
setX(Math.max(0, x - moveDimensionPx)); | |
}, | |
right: function () { | |
setX( | |
Math.min(x + moveDimensionPx, perimeterDimensionPx - objectDimensionPx) | |
); | |
}, | |
down: function () { | |
setY( | |
Math.min(y + moveDimensionPx, perimeterDimensionPx - objectDimensionPx) | |
); | |
} | |
}; | |
const Space = () => <div />; | |
const MoveButton = ({ direction }) => ( | |
<div | |
onClick={() => { | |
moveActions[direction](); | |
setActiveButton(direction); | |
}} | |
style={{ | |
backgroundColor: "lightgray", | |
cursor: "pointer", | |
...(activeButton === direction && { border: "4px ridge #80bfff" }) | |
}} | |
/> | |
); | |
return ( | |
<div | |
style={{ | |
display: "grid", | |
gridTemplateColumns: `${moveButtonWidthPx}px ${perimeterDimensionPx}px ${moveButtonWidthPx}px`, | |
gridTemplateRows: `${moveButtonWidthPx}px ${perimeterDimensionPx}px ${moveButtonWidthPx}px` | |
}} | |
> | |
<Space /> | |
<MoveButton direction="up" /> | |
<Space /> | |
<MoveButton direction="left" /> | |
<div | |
onClick={() => { | |
moveActions.reset(); | |
setActiveButton(null); | |
}} | |
> | |
<PositionedObject x={x} y={y} objectDimensionPx={objectDimensionPx}> | |
{children} | |
</PositionedObject> | |
</div> | |
<MoveButton direction="right" /> | |
<Space /> | |
<MoveButton direction="down" /> | |
</div> | |
); | |
}; | |
const ColorfulSquare = ({ dimensionPx, color }) => ( | |
<div | |
style={{ | |
height: `${dimensionPx}px`, | |
width: `${dimensionPx}px`, | |
backgroundColor: color | |
}} | |
/> | |
); | |
const Logo = ({ dimensionPx }) => ( | |
<svg | |
className="spin-logo" | |
xmlns="http://www.w3.org/2000/svg" | |
preserveAspectRatio="xMidYMid meet" | |
viewBox="0 0 72 50" | |
height={`${dimensionPx}px`} | |
width={`${dimensionPx}px`} | |
> | |
<g fill="#ff00bf"> | |
<path d="M.023.888h10.912v28.716c0 4.544 2.12 7.251 3.796 8.411-1.775 1.547-7.198 2.901-11.24-.386C1.106 35.69.022 32.504.022 29.507V.888z"></path> | |
<path d="M68.218 24.742v-3.018h3.328V11.137H67.89C66.488 4.781 60.717.018 53.815.018c-7.95 0-14.396 6.32-14.396 14.116v24.724c2.265.312 4.964-.04 7.26-1.906 2.384-1.938 3.467-5.124 3.467-8.122v-.91h5.45V17.333h-5.45v-3.199h.013c0-1.98 1.637-3.585 3.656-3.585 2.02 0 3.662 1.605 3.662 3.585v10.608c0 7.796 6.453 14.116 14.403 14.116V28.326c-2.019 0-3.662-1.605-3.662-3.584"></path> | |
<path d="M26.89 11.137v15.537c0 .883-.746 1.597-1.667 1.597-.92 0-1.667-.714-1.667-1.597V11.137H12.759V29.41c0 3.288 1.137 7.445 6.31 8.799 5.18 1.355 8.185-1.45 8.185-1.45-.274 1.848-2.049 3.201-4.909 3.491-2.164.22-4.93-.483-6.31-1.063v9.681c3.517 1.017 7.236 1.345 10.877.653 6.606-1.257 10.775-6.671 10.775-13.874v-24.51H26.891z"></path> | |
</g> | |
</svg> | |
); | |
const SelectablePositionedObject = () => { | |
const objectDimensionPx = 25; | |
const objects = [ | |
<ColorfulSquare dimensionPx={objectDimensionPx} color="#ff00bf" />, | |
<Logo dimensionPx={objectDimensionPx} />, | |
<ColorfulSquare dimensionPx={objectDimensionPx} color="blue" /> | |
]; | |
const [objectIndex, setObjectIndex] = React.useState(0); | |
const switchObject = () => setObjectIndex((objectIndex + 1) % objects.length); | |
return ( | |
<div | |
style={{ | |
display: "flex", | |
flexDirection: "column", | |
alignItems: "flex-start" | |
}} | |
> | |
<button | |
onClick={switchObject} | |
style={{ | |
margin: "10px 20px", | |
padding: "4px", | |
fontSize: "medium", | |
fontWeight: "inherit", | |
fontFamily: "inherit" | |
}} | |
> | |
Switch Object | |
</button> | |
<PositionedObjectContainer | |
perimeterDimensionPx={100} | |
moveButtonWidthPx={25} | |
moveDimensionPx={10} | |
objectDimensionPx={objectDimensionPx} | |
> | |
{objects[objectIndex]} | |
</PositionedObjectContainer> | |
</div> | |
); | |
}; | |
function App() { | |
const objectDimensionPx = 25; | |
const objects = [ | |
<ColorfulSquare dimensionPx={objectDimensionPx} color="#ff00bf" />, | |
<Logo dimensionPx={objectDimensionPx} />, | |
<ColorfulSquare dimensionPx={objectDimensionPx} color="blue" /> | |
]; | |
const [objectIndex, setObjectIndex] = React.useState(0); | |
const switchObject = () => setObjectIndex((objectIndex + 1) % objects.length); | |
return ( | |
<div | |
style={{ | |
display: "flex", | |
flexDirection: "row", | |
fontWeight: "700", | |
fontFamily: "Arial" | |
}} | |
> | |
<SelectablePositionedObject /> | |
<div style={{ marginLeft: "20px" }}> | |
<p>Requirement</p> | |
<img | |
src="https://i.imgur.com/lGlcU9C.gif" | |
alt="animated moving object" | |
width="150px" | |
/> | |
</div> | |
</div> | |
); | |
} | |
ReactDOM.render(<App />, document.getElementById("container")); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.spin-logo { | |
animation: spin-logo-spin infinite 1s linear; | |
} | |
@keyframes spin-logo-spin { | |
from { | |
transform: rotate(0deg); | |
} | |
to { | |
transform: rotate(360deg); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment