Matter.js — 如何获取图像的尺寸来设置主体大小?

2024-03-09

我正在尝试以编程方式设置 Matter.js 中链体的宽度和高度。不幸的是,我只得到 0 作为值,我不确定为什么。我的猜测是图像加载速度不够快,无法提供这些值。如何在加载图像之前加载这些尺寸?

伪代码

  • 阵列中的几具尸体
  • 获取Array中每个图像的宽度和高度
  • 使用该值设置实体尺寸

Code

var playA = Composites.stack(
  percentX(25) - assetSize / 2,
  percentY(25),
  1,
  6,
  5,
  5,
  function (x, y) {
    iA++;

    var imgWidth;
    var imgHeight;

    var img = new Image();
    img.src = String(design[iA]);

    var imgWidth = 0;
    var imgHeight = 0;

    img.onload = function a() {
      imgWidth = img.naturalWidth;
      imgHeight = img.naturalHeight;

      console.log(String(design[iA]), imgWidth, imgHeight);
    };
    console.log(String(design[iA]), imgHeight, imgWidth); // I can't access the values here.

    return Bodies.rectangle(x, y, imgWidth, imgHeight, {
      // collisionFilter: { group: group },
      friction: 1,
      render: {
        sprite: {
          texture: design[iA],
          xScale: (assetSize / 100) * 0.46,
          yScale: (assetSize / 100) * 0.46
        }
      }
    });
  }
);

Composites.chain(playA, 0.3, 0, -0.5, 0, {
  stiffness: 1,
  length: 10,
  render: { type: "line", visible: false }
});

如果您知道尺寸并且可以预先填充数组,那么解决方案可能很简单,因为 Matter.js 会加载给定 URL 字符串的图像,但需要注意的是引擎在运行之前不会等待加载。

这是迭代数组中的宽度/高度对并将这些属性传递到rectangle我将使用它作为与您的用例相匹配的示例的垫脚石。

const engine = Matter.Engine.create();
const render = Matter.Render.create({
  element: document.body,
  engine: engine,
  options: {
    width: 450,
    height: 250,
    wireframes: false, // required for images
  }
});
Matter.Render.run(render);

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

const imgSizes = [[56, 48], [45, 50], [35, 50], [60, 63]];
const stack = Matter.Composites.stack(
  // xx, yy, columns, rows, columnGap, rowGap, cb
  150, 50, 4, 1, 0, 0,
  (x, y, i) => {
    const [w, h] = imgSizes[i];
    return Matter.Bodies.rectangle(x, y, w, h, {
      render: {
        sprite: {
          texture: `http://placekitten.com/${w}/${h}` 
        }
      }
    });
  }
);
Matter.Composites.chain(stack, 0.5, 0, -0.5, 0, {
  stiffness: 0.75,
  length: 10,
  render: {type: "line", visible: true}
});

Matter.Composite.add(engine.world, [
  stack,
  Matter.Bodies.rectangle(225, 0, 450, 25, {
    isStatic: true
  }),
  Matter.Bodies.rectangle(450, 150, 25, 300, {
    isStatic: true
  }),
  Matter.Bodies.rectangle(0, 150, 25, 300, {
    isStatic: true
  }),
  Matter.Bodies.rectangle(225, 250, 450, 25, {
    isStatic: true
  })
]);

const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
  mouse: mouse,
  constraint: {
    stiffness: 0.2,
    render: {visible: true}
  }
});
Matter.Composite.add(engine.world, mouseConstraint);
render.mouse = mouse;
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>

现在,如果您需要使用加载图像onload并使用它们的尺寸,您需要使用承诺或放置all代码依赖于这些图像进入序列onload规范中描述的回调如何从异步调用返回响应? https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call.

失败的模式是:

const getSomethingAsync = cb => setTimeout(() => cb("something"), 0);

let data = null;
getSomethingAsync(result => {
  data = result;
  console.log("this runs last");
});
console.log(data); // guaranteed to be null, not "something"
// more logic that is supposed to depend on data

修复方法是:

const getSomethingAsync = cb => setTimeout(() => cb("something"), 0);

getSomethingAsync(data => {
  console.log(data);
  // logic that depends on the data from `getSomethingAsync`
});

console.log("this will run first");
// logic that doesn't depend on data from `getSomethingAsync`

既然你同时兼顾多个onloads,您可以承诺onload让他们更容易合作。我有几个这样做的例子here https://stackoverflow.com/a/58529126/6243352 and here https://stackoverflow.com/questions/61336830/trying-to-understand-context-on-canvas-concepts/61337279#61337279与 Matter.js 无关。

下面是一个使用 Promise 加载适用于您的一般问题的图像的示例。同样,我将使用我自己的代码,以便它可运行且可重现,但该模式应该很容易推断到您的项目。

这个想法是首先使用一系列承诺来加载图像,这些承诺在以下情况下得到解决:onload处理程序触发,然后使用Promise.all https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all链接一个then仅当加载所有图像时才运行 MJS 初始值设定项回调。然后,您可以在回调中访问您的 Matter.js 代码的宽度和高度。

另一个好处是,这可以确保在 MJS 运行时加载图像。

const initializeMJS = images => {
  const engine = Matter.Engine.create();
  const render = Matter.Render.create({
    element: document.body,
    engine: engine,
    options: {
      width: 450,
      height: 250,
      wireframes: false, // required for images
    }
  });
  Matter.Render.run(render);

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

  const stack = Matter.Composites.stack(
    // xx, yy, columns, rows, columnGap, rowGap, cb
    150, 50, 4, 1, 0, 0,
    (x, y, i) => {
      const {width: w, height: h} = images[i];
      return Matter.Bodies.rectangle(x, y, w, h, {
        render: {
          sprite: {
            texture: images[i].src
          }
        }
      });
    }
  );
  Matter.Composites.chain(stack, 0.5, 0, -0.5, 0, {
    stiffness: 0.75,
    length: 10,
    render: {type: "line", visible: true}
  });

  Matter.Composite.add(engine.world, [
    stack,
    Matter.Bodies.rectangle(225, 0, 450, 25, {
      isStatic: true
    }),
    Matter.Bodies.rectangle(450, 150, 25, 300, {
      isStatic: true
    }),
    Matter.Bodies.rectangle(0, 150, 25, 300, {
      isStatic: true
    }),
    Matter.Bodies.rectangle(225, 250, 450, 25, {
      isStatic: true
    })
  ]);

  const mouse = Matter.Mouse.create(render.canvas);
  const mouseConstraint = Matter.MouseConstraint.create(engine, {
    mouse: mouse,
    constraint: {
      stiffness: 0.2,
      render: {visible: true}
    }
  });
  Matter.Composite.add(engine.world, mouseConstraint);
  render.mouse = mouse;
};

const imageSizes = [[56, 48], [45, 50], [35, 50], [60, 63]];
const imageURLs = imageSizes.map(([w, h]) =>
  `http://placekitten.com/${w}/${h}`
);

Promise.all(imageURLs.map(e =>
    new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = e;
    })
  ))
  .then(initializeMJS)
;
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Matter.js — 如何获取图像的尺寸来设置主体大小? 的相关文章

  • 为什么我会收到此 Javascript 错误“连接未定义”?

    我不确定为什么会收到此错误 connection is not defined document getElementById flashTest sendValFromHtml connection value 这是我的代码 functi
  • toastr (jquery) 只能显示一次

    你能帮我限制烤面包机的外观吗 给定的情况是 当我登录系统时 欢迎 toastr 只会在主屏幕上出现一次 并且在整个会话中不会再次出现 直到我注销为止 这是我的 toastr 代码 setTimeout function toastr opt
  • 如何避免多系列折线图d3.js的工具提示重叠

    我已经在多系列折线图上创建了工具提示 如下所示在这里回答 https stackoverflow com questions 34886070 d3 js multiseries line chart with mouseover tool
  • Safari 不触发表单提交

    对于一个项目 我有两个选择表单字段 它们通过 jquery 触发器 提交 发送 这在 Firefox 和 Chrome 中运行良好 但在 Safari 中没有任何反应 这是 HTML 代码
  • YouTube 360​​ 视频 iframe 无法在移动浏览器中工作

    我正在尝试为 YouTube 360 视频获取嵌入的 iframe 以便在我的移动网站上播放 它在桌面浏览器上运行良好 但在移动浏览器中我只能播放平面立体视图 我可以确认它绝对是一个 HTML5 播放器 这显然是其他人正在经历的一个未解决的
  • Backbone Collection 和 Marionette CompositeView 中未定义的模型原型

    尝试从值列表填充集合时 我收到有关集合的错误model s prototype未定义 看着这个问题是关于类似问题的 https stackoverflow com q 16126195 1663942 我已经检查过模型确实已创建before
  • 优化重叠矩形的绘制

    我有很多矩形 有些与其他矩形重叠 每个矩形都有一个绝对 z 顺序和一个colour 每个 矩形 实际上是粒子效果 网格或纹理的轴对齐边界框 并且可能是半透明的 但只要您不尝试剔除其他矩形后面的矩形 就更容易抽象地思考彩色矩形 所以我将在问题
  • 为什么 Bootstrap 需要 jQuery? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我已经多次用谷歌搜索这个问题 但从未找到满意的答案 大多数答案似乎只是说 是的 Bootstrap 插件确实需要 jQuery https st
  • 为 Promise 编写循环的正确方法。

    如何正确构造循环以确保满足以下条件承诺电话和被束缚的记录器 log res 通过迭代同步运行 蓝鸟 db getUser email then function res logger log res this is a promise 我尝
  • 在javascript中通过window.location传递数据

    我试图通过 window location 传递数据 数据在 del id img album 中可用 我想通过 window location 发送多个值 window location save php type deldownload
  • 使用 ngx-translate 时更改 URL

    当有人使用 ngx translate 单击所选语言时 我尝试更改 URL 我想我应该通过订阅语言更改事件然后修改当前的 url 以反映所选的语言来做到这一点 因为我是新手 所以我不确定是否需要服务来做到这一点 或者可能是另一种解决方法 我
  • 为什么 if 语句中的赋值等于 true?

    首先我要说的是我理解两者之间的区别 and 第一个用于将右侧值分配给左侧变量 第二个用于比较两个值的等价性 第三个不仅用于等价性 还用于类型比较 即true 1会回来false 所以我知道almost任何时候你看到if 作者很有可能打算使用
  • 用于验证网络路径的正则表达式 PHP、jQuery、JavaScript、Ruby

    尝试找出用于验证网络路径的正则表达式 即 comp xyz or comp or comp x y z storage或者所有部分都更长的东西 但希望能够传达其要点 我目前拥有的是一个简单的输入字段 用户可以通过它传递信息 事情是我不希望他
  • 如何设置第三方 cookie

    我如何设置第三方 cookie 我有要求设置cookie 并且cookie将在访问的网站中启用 就像我在访问cde com或def com或ghi com时在abc com中设置cookie一样 所以设置的cookie将在所有网站上获取 我
  • Ajax调用完成后执行函数

    我是 Ajax 新手 我尝试在使用 for 循环时使用 Ajax Ajax 调用之后 我正在运行一个使用 Ajax 调用中创建的变量的函数 该函数只执行两次 我认为 Ajax 调用可能没有足够的时间在循环开始之前进行调用 有没有办法在运行
  • 添加元数据到快速路线

    有什么方法可以将元数据添加到 Express 的路线中吗 例如 app get some route function req res some meta data 我正在寻找一种针对我的节点应用程序的 AOP 方法 因此我想通过身份验证和
  • 通过排列四个给定数字找到最大可能时间 HH:MM

    我最近为了工作晋升而参加了编码测试 这是我真正遇到的任务之一 我想知道什么是最好的方法来做到这一点 我使用了大量的 if 和 if else 这不是最干净的解决方案 但完成了工作 我被问到的问题是 将 4 个数字格式化为 24 小时时间 0
  • 在 Javascript 中使用 fetch API 接收和处理 JSON

    在我的项目中 当条件不足时 我的 Django 应用程序会发送带有消息的 JSON 响应 我使用这个 JsonResponse 指令 Code data is taken email email return JsonResponse da
  • 来自 ajax 的 Bootstrap 表 json

    我有 ajax 和 bootstrap 表的问题 我有一个 ajax JSON 我用这个方法调用 document ready function ajax url php process php method fetchdata dataT
  • 为什么转换 new.Date() .toISOString() 会改变时间?

    我正在以两种不同的格式在数据库中插入日期 这是作为日期时间插入 var mydate mydate new Date document getElementById clockinhour value mydate toISOString

随机推荐