Problems with matter.js and i18n in vue.js

18 Views Asked by At

In this code, the language change is made when I reload the page, so I would like a solution so that it happens instantly and I don't have to reload the page.

<template>
  <div ref="scene" class="scene"></div>
</template>

<script>
import { onMounted, ref } from "vue";
import Matter from "matter-js";
import { useI18n } from "vue-i18n";

export default {
  setup() {
    const scene = ref(null);
    const balls = ref([]);
    const { t } = useI18n();

    onMounted(() => {
      const engine = Matter.Engine.create({ gravity: { x: 0, y: 0.3 } });

      const render = Matter.Render.create({
        element: scene.value,
        engine: engine,
        options: {
          width: window.innerWidth / 5,
          height: window.innerHeight / 2,
          wireframes: false,
          background: "transparent",
        },
      });

      Matter.Render.run(render);

      const createPhysicalButton = (key) => {
        const buttonWidth = 165;
        const buttonHeight = 45;
        const cornerRadius = 20;

        const x =
            Math.random() * (window.innerWidth / 8 - buttonWidth * 2 - 100) +
            buttonWidth +
            50;
        const y =
            Math.random() * (window.innerHeight / 2 - buttonHeight * 2 - 100) +
            buttonHeight +
            50;
        const angle = Math.random() * Math.PI * 2;

        const body = Matter.Bodies.rectangle(x, y, buttonWidth, buttonHeight, {
          chamfer: { radius: cornerRadius },
          angle: angle,
          isStatic: false,
          restitution: 0.4,
          frictionAir: 0.004,
          density: 0.01,
          render: { visible: false },
        });
        body.initialPosition = { x, y };

        const button = document.createElement("button");
        button.innerText = t(key);
        button.style.padding = "10px";
        button.style.borderRadius = `${cornerRadius}px`;
        button.style.border = "1px solid #333";
        button.style.backgroundColor = "transparent";
        button.style.position = "absolute";
        button.style.left = `${x - buttonWidth / 2}px`;
        button.style.top = `${y - buttonHeight / 2}px`;
        button.style.width = `${buttonWidth}px`;
        button.style.height = `${buttonHeight}px`;
        scene.value.appendChild(button);

        const limiterVitesse = (corps, vitesseMax) => {
          const vitesse = Matter.Vector.magnitude(corps.velocity);
          if (vitesse > vitesseMax) {
            Matter.Body.setVelocity(
                corps,
                Matter.Vector.mult(
                    Matter.Vector.normalise(corps.velocity),
                    vitesseMax
                )
            );
          }
        };

        Matter.Events.on(engine, "afterUpdate", () => {
          button.style.left = `${body.position.x - buttonWidth / 2}px`;
          button.style.top = `${body.position.y - buttonHeight / 2}px`;
          button.style.transform = `rotate(${body.angle}rad)`;
          [...balls.value, ...buttons].forEach((corps) =>
              limiterVitesse(corps, 10)
          );

          const maxSpeed = 10;
          const speed = Matter.Vector.magnitude(body.velocity);
          if (speed > maxSpeed) {
            Matter.Body.setVelocity(
                body,
                Matter.Vector.mult(
                    Matter.Vector.normalise(body.velocity),
                    maxSpeed
                )
            );
          }
        });

        return body;
      };

      const buttons = [
        createPhysicalButton("button.fun"),
        createPhysicalButton("button.awareness"),
        createPhysicalButton("button.act"),
        createPhysicalButton("button.enjoy"),
        createPhysicalButton("button.learn"),
        createPhysicalButton("button.ecology"),
        createPhysicalButton("button.education"),
      ];

      Matter.World.add(engine.world, buttons);

      const colors = ["#551126", "#C1DD13", "#ABCDFF"];

      const createBall = (color) => {
        const ballSize = 6;
        const x =
            Math.random() * (window.innerWidth / 8 - ballSize * 2 - 100) +
            ballSize +
            50;
        const y =
            Math.random() * (window.innerHeight / 2 - ballSize * 2 - 100) +
            ballSize +
            50;
        const angle = Math.random() * Math.PI * 2;

        const ball = Matter.Bodies.circle(x, y, ballSize, {
          angle: angle,
          isStatic: false,
          restitution: 0.4,
          frictionAir: 0.004,
          density: 0.01,
          render: {
            fillStyle: color,
            strokeStyle: "transparent",
          },
        });

        balls.value.push(ball);
        Matter.World.add(engine.world, ball);

        return ball;
      };

      const createdBalls = colors.map((color) => createBall(color));

      Matter.World.add(engine.world, createdBalls);

      const wallOptions = {
        isStatic: true,
        render: { visible: false },
      };

      const wallThickness = 200; // Augmentez l'épaisseur des murs pour empêcher le passage des balles

      // Assurez-vous que la position et la taille des murs couvrent correctement les bords de la scène
      const leftWall = Matter.Bodies.rectangle(-wallThickness / 2, window.innerHeight / 4, wallThickness, window.innerHeight * 2, wallOptions);
      const rightWall = Matter.Bodies.rectangle(window.innerWidth / 5 + wallThickness / 2, window.innerHeight / 4, wallThickness, window.innerHeight * 2, wallOptions);

      const topWall = Matter.Bodies.rectangle(
          window.innerWidth / 16,
          -wallThickness / 2,
          window.innerWidth * 2,
          wallThickness,
          wallOptions
      );
      const bottomWall = Matter.Bodies.rectangle(
          window.innerWidth / 16,
          window.innerHeight / 2 + wallThickness / 2,
          window.innerWidth * 2,
          wallThickness,
          wallOptions
      );

      Matter.World.add(engine.world, [
        leftWall,
        rightWall,
        topWall,
        bottomWall,
      ]);

      Matter.Events.on(engine, "collisionStart", (event) => {
        event.pairs.forEach((pair) => {
          const { bodyA, bodyB } = pair;

          if (
              balls.value.includes(bodyA) &&
              (leftWall === bodyB ||
                  rightWall === bodyB ||
                  topWall === bodyB ||
                  bottomWall === bodyB)
          ) {
            Matter.Body.setVelocity(bodyA, {
              x: -bodyA.velocity.x * 0.5,
              y: -bodyA.velocity.y * 0.5,
            });
          }

          if (
              balls.value.includes(bodyB) &&
              (leftWall === bodyA ||
                  rightWall === bodyA ||
                  topWall === bodyA ||
                  bottomWall === bodyA)
          ) {
            Matter.Body.setVelocity(bodyB, {
              x: -bodyB.velocity.x * 0.5,
              y: -bodyB.velocity.y * 0.5,
            });
          }
        });
      });

      let lastMousePosition = { x: 0, y: 0 };

      window.addEventListener("mousemove", (event) => {
        const sceneRect = scene.value.getBoundingClientRect();
        const mousePosition = {
          x: event.clientX - sceneRect.left,
          y: event.clientY - sceneRect.top,
        };
        const mouseVelocity = {
          x: mousePosition.x - lastMousePosition.x,
          y: mousePosition.y - lastMousePosition.y,
        };

        buttons.forEach((button) => {
          const distance = Matter.Vector.magnitude(
              Matter.Vector.sub(button.position, mousePosition)
          );
          if (distance < 50 && Matter.Vector.magnitude(mouseVelocity) > 0) {
            const maxMouseSpeed = 20;
            const buttonSpeed = Matter.Vector.magnitude(mouseVelocity);
            if (buttonSpeed > maxMouseSpeed) {
              Matter.Body.setVelocity(
                  button,
                  Matter.Vector.mult(
                      Matter.Vector.normalise(mouseVelocity),
                      maxMouseSpeed
                  )
              );
            } else {
              Matter.Body.setVelocity(button, mouseVelocity);
            }
          }
        });

        balls.value.forEach((ball) => {
          const distance = Matter.Vector.magnitude(
              Matter.Vector.sub(ball.position, mousePosition)
          );
          if (distance < 50 && Matter.Vector.magnitude(mouseVelocity) > 0) {
            const maxMouseSpeed = 20;
            const ballSpeed = Matter.Vector.magnitude(mouseVelocity);
            if (ballSpeed > maxMouseSpeed) {
              Matter.Body.setVelocity(
                  ball,
                  Matter.Vector.mult(
                      Matter.Vector.normalise(mouseVelocity),
                      maxMouseSpeed
                  )
              );
            } else {
              Matter.Body.setVelocity(ball, mouseVelocity);
            }
          }
        });

        lastMousePosition = mousePosition;
      });

      const runner = Matter.Runner.create();
      Matter.Runner.run(runner, engine);
    });

    return { scene };
  },
};
</script>

<style>
.scene {
  width: 50vw;
  height: 30vh;
  position: absolute; /* ou 'relative' selon le besoin */
  top: 60%;
  left: 73%;
  transform: translate(-50%, -50%);
  margin-top: 100px;
}

button {
  z-index: 10;
  border-radius: 20px;
  border: 1px solid #333;
  background-color: transparent;
  transform-origin: center center;
  cursor: auto;
}

</style>

In this case, I don't need to reload the page, but the buttons are no longer subject to the same reactivity as before.

<template>
  <div ref="scene" class="scene"></div>
</template>

<script>
import { onMounted, ref, watch } from "vue";
import Matter from "matter-js";
import { useI18n } from "vue-i18n";

export default {
  setup() {
    const scene = ref(null);
    const balls = ref([]);
    const buttons = ref([]);
    const { t, locale } = useI18n();

    const updatePhysicalButtons = () => {
      if (!scene.value) {
        console.warn("Scene not ready.");
        return;
      }

      const existingButtons = scene.value.querySelectorAll('button');
      existingButtons.forEach(button => button.remove());

      const buttonKeys = [
        "button.fun",
        "button.awareness",
        "button.act",
        "button.enjoy",
        "button.learn",
        "button.ecology",
        "button.education",
      ];
      buttonKeys.forEach(key => createPhysicalButton(key));
    };

    const createPhysicalButton = (key) => {
      const buttonWidth = 165;
      const buttonHeight = 45;
      const cornerRadius = 20;

      const x =
          Math.random() * (window.innerWidth / 8 - buttonWidth * 2 - 100) +
          buttonWidth +
          50;
      const y =
          Math.random() * (window.innerHeight / 2 - buttonHeight * 2 - 100) +
          buttonHeight +
          50;
      const angle = Math.random() * Math.PI * 2;

      const body = Matter.Bodies.rectangle(x, y, buttonWidth, buttonHeight, {
        chamfer: { radius: cornerRadius },
        angle: angle,
        isStatic: false,
        restitution: 0.4,
        frictionAir: 0.004,
        density: 0.01,
        render: { visible: false },
      });
      body.initialPosition = { x, y };

      const button = document.createElement("button");
      button.innerText = t(key);
      button.style.padding = "10px";
      button.style.borderRadius = `${cornerRadius}px`;
      button.style.border = "1px solid #333";
      button.style.backgroundColor = "transparent";
      button.style.position = "absolute";
      button.style.left = `${x - buttonWidth / 2}px`;
      button.style.top = `${y - buttonHeight / 2}px`;
      button.style.width = `${buttonWidth}px`;
      button.style.height = `${buttonHeight}px`;
      scene.value.appendChild(button);

      const limiterVitesse = (corps, vitesseMax) => {
        const vitesse = Matter.Vector.magnitude(corps.velocity);
        if (vitesse > vitesseMax) {
          Matter.Body.setVelocity(
              corps,
              Matter.Vector.mult(
                  Matter.Vector.normalise(corps.velocity),
                  vitesseMax
              )
          );
        }
      };

      Matter.Events.on(engine, "afterUpdate", () => {
        button.style.left = `${body.position.x - buttonWidth / 2}px`;
        button.style.top = `${body.position.y - buttonHeight / 2}px`;
        button.style.transform = `rotate(${body.angle}rad)`;
        [...balls.value, ...buttons.value].forEach((corps) =>
            limiterVitesse(corps, 10)
        );

        const maxSpeed = 10;
        const speed = Matter.Vector.magnitude(body.velocity);
        if (speed > maxSpeed) {
          Matter.Body.setVelocity(
              body,
              Matter.Vector.mult(
                  Matter.Vector.normalise(body.velocity),
                  maxSpeed
              )
          );
        }
      });

      buttons.value.push(body);

      return body;
    };

    let engine;

    onMounted(() => {
      engine = Matter.Engine.create({ gravity: { x: 0, y: 0.3 } });
      const render = Matter.Render.create({
        element: scene.value,
        engine: engine,
        options: {
          width: window.innerWidth / 5,
          height: window.innerHeight / 2,
          wireframes: false,
          background: "transparent",
        },
      });

      Matter.Render.run(render);
      updatePhysicalButtons();

      const colors = ["#551126", "#C1DD13", "#ABCDFF"];

      const createBall = (color) => {
        const ballSize = 6;
        const x =
            Math.random() * (window.innerWidth / 8 - ballSize * 2 - 100) +
            ballSize +
            50;
        const y =
            Math.random() * (window.innerHeight / 2 - ballSize * 2 - 100) +
            ballSize +
            50;
        const angle = Math.random() * Math.PI * 2;

        const ball = Matter.Bodies.circle(x, y, ballSize, {
          angle: angle,
          isStatic: false,
          restitution: 0.4,
          frictionAir: 0.004,
          density: 0.01,
          render: {
            fillStyle: color,
            strokeStyle: "transparent",
          },
        });

        balls.value.push(ball);
        Matter.World.add(engine.world, ball);

        return ball;
      };

      const createdBalls = colors.map((color) => createBall(color));

      Matter.World.add(engine.world, createdBalls);

      const wallOptions = {
        isStatic: true,
        render: { visible: false },
      };

      const wallThickness = 200;

      const leftWall = Matter.Bodies.rectangle(-wallThickness / 2, window.innerHeight / 4, wallThickness, window.innerHeight * 2, wallOptions);
      const rightWall = Matter.Bodies.rectangle(window.innerWidth / 5 + wallThickness / 2, window.innerHeight / 4, wallThickness, window.innerHeight * 2, wallOptions);

      const topWall = Matter.Bodies.rectangle(
          window.innerWidth / 16,
          -wallThickness / 2,
          window.innerWidth * 2,
          wallThickness,
          wallOptions
      );
      const bottomWall = Matter.Bodies.rectangle(
          window.innerWidth / 16,
          window.innerHeight / 2 + wallThickness / 2,
          window.innerWidth * 2,
          wallThickness,
          wallOptions
      );

      Matter.World.add(engine.world, [
        leftWall,
        rightWall,
        topWall,
        bottomWall,
      ]);

      Matter.Events.on(engine, "collisionStart", (event) => {
        event.pairs.forEach((pair) => {
          const { bodyA, bodyB } = pair;

          if (
              balls.value.includes(bodyA) &&
              (leftWall === bodyB ||
                  rightWall === bodyB ||
                  topWall === bodyB ||
                  bottomWall === bodyB)
          ) {
            Matter.Body.setVelocity(bodyA, {
              x: -bodyA.velocity.x * 0.5,
              y: -bodyA.velocity.y * 0.5,
            });
          }

          if (
              balls.value.includes(bodyB) &&
              (leftWall === bodyA ||
                  rightWall === bodyA ||
                  topWall === bodyA ||
                  bottomWall === bodyA)
          ) {
            Matter.Body.setVelocity(bodyB, {
              x: -bodyB.velocity.x * 0.5,
              y: -bodyB.velocity.y * 0.5,
            });
          }
        });
      });

      let lastMousePosition = { x: 0, y: 0 };

      window.addEventListener("mousemove", (event) => {
        const sceneRect = scene.value.getBoundingClientRect();
        const mousePosition = {
          x: event.clientX - sceneRect.left,
          y: event.clientY - sceneRect.top,
        };
        const mouseVelocity = {
          x: mousePosition.x - lastMousePosition.x,
          y: mousePosition.y - lastMousePosition.y,
        };

        buttons.value.forEach((button) => {
          const distance = Matter.Vector.magnitude(
              Matter.Vector.sub(button.position, mousePosition)
          );
          if (distance < 50 && Matter.Vector.magnitude(mouseVelocity) > 0) {
            const maxMouseSpeed = 20;
            const buttonSpeed = Matter.Vector.magnitude(mouseVelocity);
            if (buttonSpeed > maxMouseSpeed) {
              Matter.Body.setVelocity(
                  button,
                  Matter.Vector.mult(
                      Matter.Vector.normalise(mouseVelocity),
                      maxMouseSpeed
                  )
              );
            } else {
              Matter.Body.setVelocity(button, mouseVelocity);
            }
          }
        });

        balls.value.forEach((ball) => {
          const distance = Matter.Vector.magnitude(
              Matter.Vector.sub(ball.position, mousePosition)
          );
          if (distance < 50 && Matter.Vector.magnitude(mouseVelocity) > 0) {
            const maxMouseSpeed = 20;
            const ballSpeed = Matter.Vector.magnitude(mouseVelocity);
            if (ballSpeed > maxMouseSpeed) {
              Matter.Body.setVelocity(
                  ball,
                  Matter.Vector.mult(
                      Matter.Vector.normalise(mouseVelocity),
                      maxMouseSpeed
                  )
              );
            } else {
              Matter.Body.setVelocity(ball, mouseVelocity);
            }
          }
        });

        lastMousePosition = mousePosition;
      });

      const runner = Matter.Runner.create();
      Matter.Runner.run(runner, engine);
    });

    watch(locale, () => {
      updatePhysicalButtons();
    }, { immediate: true });

    return { scene };
  },
};
</script>

<style>
.scene {
  width: 50vw;
  height: 30vh;
  position: absolute;
  top: 60%;
  left: 73%;
  transform: translate(-50%, -50%);
  margin-top: 100px;
}

button {
  z-index: 10;
  border-radius: 20px;
  border: 1px solid #333;
  background-color: transparent;
  transform-origin: center center;
  cursor: auto;
}
</style>

So I tried the things said above

0

There are 0 best solutions below