DiceImage.jsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import React, { memo } from "react";
  2. import styled from "styled-components";
  3. import { useItemInteraction } from "react-sync-board";
  4. import { media2Url } from "../mediaLibrary";
  5. const DicePane = styled.div`
  6. line-height: 0;
  7. img {
  8. ${({ width }) => (width ? `width: ${width}px;` : "")}
  9. ${({ height }) =>
  10. height ? `height: ${height}px;` : ""}
  11. pointer-events: none;
  12. }
  13. `;
  14. const getRandomInt = (sides) => {
  15. let min = 1;
  16. let max = Math.ceil(sides);
  17. return Math.floor(Math.random() * max) + min;
  18. };
  19. const defaultDiceImages = [
  20. "/game_assets/dice/one.svg",
  21. "/game_assets/dice/two.svg",
  22. "/game_assets/dice/three.svg",
  23. "/game_assets/dice/four.svg",
  24. "/game_assets/dice/five.svg",
  25. "/game_assets/dice/six.svg",
  26. ];
  27. const Dice = ({
  28. id,
  29. value = 0,
  30. side = 6,
  31. images = defaultDiceImages,
  32. width = 50,
  33. height = 50,
  34. rollOnDblClick = false,
  35. setState,
  36. }) => {
  37. const { register } = useItemInteraction("place");
  38. const diceWrapper = React.useRef(null);
  39. const roll = React.useCallback(() => {
  40. diceWrapper.current.className = "hvr-wobble-horizontal";
  41. const simulateRoll = (nextTimeout) => {
  42. setState((prevState) => ({
  43. ...prevState,
  44. value: getRandomInt(side - 1),
  45. }));
  46. if (nextTimeout < 200) {
  47. setTimeout(
  48. () => simulateRoll(nextTimeout + getRandomInt(30)),
  49. nextTimeout
  50. );
  51. }
  52. };
  53. simulateRoll(100);
  54. }, [setState, side]);
  55. const removeClass = (e) => {
  56. e.target.className = "";
  57. };
  58. React.useEffect(() => {
  59. const unregisterList = [];
  60. if (!rollOnDblClick) {
  61. const rollOnPlace = (itemIds) => {
  62. if (itemIds.includes(id)) {
  63. roll();
  64. }
  65. };
  66. unregisterList.push(register(rollOnPlace));
  67. }
  68. return () => {
  69. unregisterList.forEach((callback) => callback());
  70. };
  71. }, [roll, register, rollOnDblClick, id]);
  72. return (
  73. <div onAnimationEnd={removeClass} ref={diceWrapper}>
  74. <DicePane
  75. width={width}
  76. height={height}
  77. onDoubleClick={() => (rollOnDblClick ? roll() : null)}
  78. >
  79. {images[value] && <img src={media2Url(images[value])} />}
  80. </DicePane>
  81. </div>
  82. );
  83. };
  84. export default memo(Dice);