繁体   English   中英

如何使项目可拖动和可点击?

[英]How to make items draggable and clickable?

我是 Matter JS 的新手,所以请耐心等待。 我从演示和其他来源整理了以下代码以满足我的需求:

function biscuits(width, height, items, gutter) {
  const {
    Engine,
    Render,
    Runner,
    Composites,
    MouseConstraint,
    Mouse,
    World,
    Bodies,
  } = Matter

  const engine = Engine.create()
  const world = engine.world

  const render = Render.create({
    element: document.getElementById('canvas'),
    engine,
    options: {
      width,
      height,
      showAngleIndicator: true,
    },
  })

  Render.run(render)

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

  const columns = media({ bp: 'xs' }) ? 3 : 1
  const stack = Composites.stack(
    getRandom(gutter, gutter * 2),
    gutter,
    columns,
    items.length,
    0,
    0,
    (x, y, a, b, c, i) => {
      const item = items[i]

      if (!item) {
        return null
      }

      const {
        width: itemWidth,
        height: itemHeight,
      } = item.getBoundingClientRect()

      const radiusAmount = media({ bp: 'sm' }) ? 100 : 70
      const radius = item.classList.contains('is-biscuit-4')
        ? radiusAmount
        : 0
      const shape = item.classList.contains('is-biscuit-2')
        ? Bodies.circle(x, y, itemWidth / 2)
        : Bodies.rectangle(x, y, itemWidth, itemHeight, {
            chamfer: { radius },
          })

      return shape
    }
  )

  World.add(world, stack)

  function positionDomElements() {
    Engine.update(engine, 20)

    stack.bodies.forEach((block, index) => {
      const item = items[index]
      const xTrans = block.position.x - item.offsetWidth / 2 - gutter / 2
      const yTrans = block.position.y - item.offsetHeight / 2 - gutter / 2

      item.style.transform = `translate3d(${xTrans}px, ${yTrans}px, 0) rotate(${block.angle}rad)`
    })

    window.requestAnimationFrame(positionDomElements)
  }

  positionDomElements()

  World.add(world, [
    Bodies.rectangle(width / 2, 0, width, gutter, { isStatic: true }),
    Bodies.rectangle(width / 2, height, width, gutter, { isStatic: true }),
    Bodies.rectangle(width, height / 2, gutter, height, { isStatic: true }),
    Bodies.rectangle(0, height / 2, gutter, height, { isStatic: true }),
  ])

  const mouse = Mouse.create(render.canvas)
  const mouseConstraint = MouseConstraint.create(engine, {
    mouse,
    constraint: {
      stiffness: 0.2,
      render: {
        visible: false,
      },
    },
  })

  World.add(world, mouseConstraint)

  render.mouse = mouse

  Render.lookAt(render, {
    min: { x: 0, y: 0 },
    max: { x: width, y: height },
  })
}

我有一个 HTML 链接列表,它模仿 Matter JS 中项目的移动(positionDomElements 函数)。 我这样做是为了 SEO 目的,也是为了使导航可访问和可点击。

但是,因为我的画布位于 HTML 的顶部(不透明度为零),所以我需要能够使项目可点击和可拖动,以便我可以执行一些其他操作,例如导航到链接(和其他事件) .

我不知道该怎么做。 我四处寻找,但我没有任何运气。

是否可以让每个项目都可拖动(因为它已经是)并执行某种点击事件?

任何帮助或引导正确方向将不胜感激。

您的任务似乎是将物理添加到一组 DOM 导航列表节点。 您可能会觉得,matter.js 需要提供一个画布才能运行,如果您想忽略它,则需要隐藏画布或将其不透明度设置为 0。

实际上,您可以使用自己的更新循环无头地运行 MJS,而无需将元素注入引擎。 实际上,不需要与Matter.RenderMatter.Runner相关的任何内容,您可以调用Matter.Engine.update(engine); 使引擎在requestAnimationFrame循环中前进一个刻度。 然后,您可以使用从 MJS 主体中提取的值来定位 DOM 元素。 你已经在做这两件事,所以主要是剪掉画布和渲染调用。

这是一个可运行的示例,您可以参考并适应您的用例。

定位是最难的部分; 确保 MJS 坐标与您的鼠标和元素坐标匹配需要一些大惊小怪。 MJS 将 x/y 坐标视为身体的中心,所以我使用body.vertices[0]作为左上角,更好地匹配 DOM。 我想很多这些渲染决策都是特定于应用程序的,因此将其视为概念验证。

 const listEls = document.querySelectorAll("#mjs-wrapper li"); const engine = Matter.Engine.create(); const stack = Matter.Composites.stack( // xx, yy, columns, rows, columnGap, rowGap, cb 0, 0, listEls.length, 1, 0, 0, (xx, yy, i) => { const {x, y, width, height} = listEls[i].getBoundingClientRect(); return Matter.Bodies.rectangle(x, y, width, height, { isStatic: i === 0 || i + 1 === listEls.length }); } ); Matter.Composites.chain(stack, 0.5, 0, -0.5, 0, { stiffness: 0.5, length: 20 }); const mouseConstraint = Matter.MouseConstraint.create( engine, {element: document.querySelector("#mjs-wrapper")} ); Matter.World.add(engine.world, [stack, mouseConstraint]); listEls.forEach(e => { e.style.position = "absolute"; e.addEventListener("click", e => console.log(e.target.textContent) ); }); (function update() { requestAnimationFrame(update); stack.bodies.forEach((block, i) => { const li = listEls[i]; const {x, y} = block.vertices[0]; li.style.top = `${y}px`; li.style.left = `${x}px`; li.style.transform = `translate(-50%, -50%) rotate(${block.angle}rad) translate(50%, 50%)`; }); Matter.Engine.update(engine); })();
 * { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; } body { min-width: 600px; } #mjs-wrapper { /* position this element */ margin: 1em; height: 100%; } #mjs-wrapper ul { font-size: 14pt; list-style: none; user-select: none; position: relative; } #mjs-wrapper li { background: #fff; border: 1px solid #555; display: inline-block; padding: 1em; cursor: move; } #mjs-wrapper li:hover { background: #f2f2f2; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script> <div id="mjs-wrapper"> <ul> <li>Foo</li> <li>Bar</li> <li>Baz</li> <li>Quux</li> <li>Garply</li> <li>Corge</li> </ul> </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM