Matter.js Настройка управления мышью

Я пытаюсь добавить элементы управления мышью в начальный пример Matter.js из двух блоков. Кажется, я что-то упускаю, потому что это не сработает. Я просто хочу иметь возможность перемещать тела с помощью мыши.

Я пытаюсь добавить элементы управления мышью в начальный пример Matter.js из двух блоков. Кажется, я что-то упускаю, потому что это не сработает. Я просто хочу иметь возможность перемещать тела с помощью мыши.

'''

<canvas id = "canvasM" data-pixel-ratio = "2" style = "position:relative; z-index:0;"></canvas>
<script>
      // module aliases
  var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite;
      World = Matter.World;
  
  var mouse;
  
  // create an engine
  var engine = Engine.create();
    world = engine.world;
  
  var w = window.innerWidth;
  var h = window.innerHeight;
  
  // create two boxes and a ground
  var boxA = Bodies.rectangle(.5*w+30, .7*h, 80, 80);
  var boxB = Bodies.rectangle(.5*w+60, 50, 80, 80);
  var ground = Bodies.rectangle(.5*w-1, .888*h+.05*h-30+1.5, w, .1*h, { isStatic: true });

  // add all of the bodies to the world
  Composite.add(engine.world, 
                [boxA, boxB, ground]);
  

  // create runner
  var runner = Runner.create();

  // run the engine
  Runner.run(runner, engine);
  
  var canvas = document.getElementById('canvasM');
  context = canvas.getContext('2d');
  canvas.width = window.innerWidth-130;
  canvas.height = 0.888*window.innerHeight;


  
  (function render() {
      var bodies = Composite.allBodies(engine.world);

      window.requestAnimationFrame(render);

      context.beginPath();

      for (var i = 0; i < bodies.length; i += 1) {
          var vertices = bodies[i].vertices;

          context.moveTo(vertices[0].x, vertices[0].y);

          for (var j = 1; j < vertices.length; j += 1) {
              context.lineTo(vertices[j].x, vertices[j].y);
          }

          context.lineTo(vertices[0].x, vertices[0].y);
      }

      context.lineWidth = 3;
      context.fill = '#fff';
      context.strokeStyle = '#000';
      context.stroke();
    

  var mouseC = Matter.MouseConstraint;
  mouseC.pixelRatio = 2;
  var canvmouse = Matter.Mouse.create(document.getElementById('canvasM'));
  mouseC = mouseC.create(engine,{
        mouse: canvmouse});

  Composite.add(world, mouseC);

  render.mouse = mouse;
  
  })();
  
  
  
</script>

'''

Нет смысла добавлять ограничение мыши 60 раз в секунду в цикле рендеринга. Сделайте это один раз заранее, как показано в Использование Matter.js для рендеринга в DOM или React.

ggorlen 14.10.2022 02:17

Я сделал это, потому что больше ничего не работало, попытался скопировать мышь из примера, который вы разместили, но ничего не получилось.

oak 14.10.2022 23:49

Да, ваша установка здесь имеет несколько фундаментальных проблем. Например, необычно вызывать requestAnimationFrame, когда вы также используете внутренний бегун MJS, который делает то же самое для вас. Из документации: «Если вместо этого вы используете свой собственный игровой цикл, вам не нужен модуль Matter.Runner». Неясно, хотите ли вы использовать свой собственный цикл или MJS. Какой ты хочешь? Я предлагаю использовать связанный пример в качестве основы для создания вашего приложения, а не наоборот. Это работает, поэтому вы можете адаптировать его к своему варианту использования.

ggorlen 14.10.2022 23:50

нашел ошибку, это было что-то с моим именем переменной. (ваш ответ помог мне сфокусироваться) Теперь система координат, кажется, отключена, и я учел соотношение пикселей, но после этого я понял.

oak 15.10.2022 00:17

Большой. Не стесняйтесь публиковать самостоятельный ответ, если вы решили свою проблему, но я бы предостерег от этого дизайна, не задумываясь, даже если он работает (вы все еще можете запускать два цикла событий одновременно, что в лучшем случае вредно для производительности, а в худшем чревато ошибками).

ggorlen 15.10.2022 00:19

Я опубликую ответ, когда у меня будет система координат (есть мысли?). Прямо сейчас я взаимодействую только с формами на расстоянии около дюйма. Также не знаю, как реализовать один цикл, как вы сказали, потому что, когда я убираю один, другой перестает работать.

oak 15.10.2022 00:28

Есть два варианта: использовать цикл бегуна MJS или собственный цикл, но не оба. Я просто буду продолжать отсылать вас к приведенному выше рабочему примеру, как для координат, так и для цикла рендеринга. Если вы используете свой цикл, вызовите engine.update() внутри цикла RAF, как показано в примере.

ggorlen 15.10.2022 00:40

О, извините, вы используете холст, а не DOM, но концепция почти такая же. codepen.io/ggorlen/full/LOwrxX пример с холстом, мышью и правильными координатами. Кажется, я не могу найти свои примеры холстов на SO, поэтому я добавлю ответ, если у меня будет время.

ggorlen 15.10.2022 00:53

Кажется, я не вижу, как ваши координаты мыши в основном запекаются, а мои выключены.

oak 15.10.2022 01:05

Давайте продолжим обсуждение в чате.

oak 15.10.2022 01:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
10
78
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как упоминалось в комментариях, создание бегуна Matter и использование собственного цикла обновления являются взаимоисключающими. Если вы хотите использовать средство запуска MJS, подключитесь к событиям обновления и при необходимости перерисуйте свой пользовательский интерфейс. Если вы предпочитаете использовать собственный цикл обновления, пропустите средство визуализации и вызовите Matter.update() в цикле.

Вот пример использования собственного цикла:

const w = window.innerWidth;
const h = window.innerHeight;
const engine = Matter.Engine.create();

const boxA = Matter.Bodies.rectangle(
  0.5 * w + 30, // x
  0.7 * h, // y
  80, // w
  80, // h
);
const boxB = Matter.Bodies.rectangle(
  0.5 * w + 60,
  50,
  80,
  80
);
const ground = Matter.Bodies.rectangle(
  0.5 * w - 1,
  0.888 * h + 0.05 * h - 30 + 1.5,
  w,
  0.1 * h,
  {
    isStatic: true,
  }
);

const canvas = document.querySelector("canvas");
const context = canvas.getContext("2d");
canvas.width = w - 130;
canvas.height = 0.888 * h;

const mouseConstraint = Matter.MouseConstraint.create(
  engine,
  {element: canvas}
);
Matter.Composite.add(engine.world, [
  boxA,
  boxB,
  ground,
  mouseConstraint,
]);
const bodies = Matter.Composite.allBodies(engine.world);

(function render() {
  window.requestAnimationFrame(render);

  context.clearRect(0, 0, canvas.width, canvas.height);
  context.beginPath();

  for (const {vertices} of bodies) {
    context.moveTo(vertices[0].x, vertices[0].y);
    vertices.forEach(({x, y}) => context.lineTo(x, y));
    context.lineTo(vertices[0].x, vertices[0].y);
  }

  context.lineWidth = 3;
  context.fill = "#fff";
  context.strokeStyle = "#000";
  context.stroke();

  Matter.Engine.update(engine);
})();
<script src = "https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
<canvas></canvas>

Не работает с управлением мышью, когда я реализую

oak 16.10.2022 04:26

Не уверен, что вы имеете в виду - это отлично работает для меня.

ggorlen 16.10.2022 06:43

да wierd работает на codepen не на моем сайте по какой-то причине

oak 16.10.2022 18:18

У вас есть ссылка на сайт? Может, в консоли какие-то ошибки или какой-то другой фактор?

ggorlen 16.10.2022 20:39
Ответ принят как подходящий

Ниже приведено исправление моего кода. См. переменную с именем mouseControl и, в частности, Matter.Mouse.setScale(canvmouse,{x:2,y:2});, чтобы исправить масштабирование координат мыши. Отдельное спасибо @ggorlen за внимание и информирование о избыточности петли.


<script src = "https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>

<canvas id = "canvasM" data-pixel-ratio = "2" style = "position:relative; z-index:0;"></canvas>
<script>
      // module aliases
  var Engine = Matter.Engine,
      Render = Matter.Render,
      Runner = Matter.Runner,
      Bodies = Matter.Bodies,
      Composite = Matter.Composite;
      World = Matter.World;
  
  var mouse;
  
  // create an engine
  var engine = Engine.create();
    world = engine.world;
  
  var w = window.innerWidth;
  var h = window.innerHeight;
  
  // create two boxes and a ground
  var boxA = Bodies.rectangle(.5*w+30, .7*h, 80, 80);
  var boxB = Bodies.rectangle(.5*w+60, 50, 80, 80);
  var ground = Bodies.rectangle(.5*w-1, .888*h+.05*h-30+1.5, w, .1*h, { isStatic: true });

  // add all of the bodies to the world
  Composite.add(engine.world, 
                [boxA, boxB, ground]);
  

  
  var canvas = document.getElementById('canvasM');
  context = canvas.getContext('2d');
  canvas.width = window.innerWidth-130;
  canvas.height = 0.888*window.innerHeight;


  
  (function render() {
      var bodies = Composite.allBodies(engine.world);

      window.requestAnimationFrame(render);

      context.beginPath();

      for (var i = 0; i < bodies.length; i += 1) {
          var vertices = bodies[i].vertices;

          context.moveTo(vertices[0].x, vertices[0].y);

          for (var j = 1; j < vertices.length; j += 1) {
              context.lineTo(vertices[j].x, vertices[j].y);
          }

          context.lineTo(vertices[0].x, vertices[0].y);
      }

      context.lineWidth = 3;
      context.fill = '#fff';
      context.strokeStyle = '#000';
      context.stroke();
    
  Matter.Engine.update(engine);
  })();
  
  var mouseC = Matter.MouseConstraint;
  var canvmouse = Matter.Mouse.create(document.getElementById('canvasM'));
  Matter.Mouse.setScale(canvmouse,{x:2,y:2});

  mouseControl = mouseC.create(engine,{
        mouse: canvmouse});

  Composite.add(world, mouseControl);

  render.mouse = mouse;
  
  
</script>


Другие вопросы по теме