how to round an image in matter.js
Asked Answered
R

2

4

When a sphere falls I would like to put images inside but it doesn't work with the fillStyle render I can only color, now with sprite I can but they don't fit the circle unless the image is rounded, how could I round the image with javascript and matter.js

the code:

return Matter.Bodies.circle(280, 40, 11, {
    restitution: 0.5,
    render: {
        // fillStyle: '#F00',
        // strokeStyle: 'black',
        // lineWidth: 3,
        sprite: {
            texture: img,
            xScale: 0.3,
            yScale: 0.3,  
        }
    }
    
});

img get square images from ticktok, which I don't know how to make the round

Rondon answered 1/6, 2022 at 22:50 Comment(0)
P
1

I'm not 100% sure, if this is the best way to do it (in you specific usecase), but you could just :

  • create a helper canvas Element:
    <canvas id='helper-canvas'></canvas> or let canvas = document.createElement('canvas');

  • set the width/height of the canvas (width = desired texture width)

    ...
    canvas.width='100';
    canvas.height='100';
    ...
    
  • draw the image onto a canvas element(using the context).

    ...
    ctx.drawImage(img, 0, 0); // "img" is a HtmlImageElement
    ...
    
  • set composite-mode and draw a circle that should have the desired size

    ...
    ctx.globalCompositeOperation='destination-in';
    ctx.beginPath();
    ctx.arc(img.width/2,img.width/2,img.width/2,0,Math.PI*2);
    ctx.closePath();
    ctx.fill();
    ...
    
  • generate the url of the new "create image"

    ...
    let imgUrl = img.toDataURL('image/png'); 
    ...
    

And than simply create the matter-body, with that image:

Matter.Bodies.circle(280, 40, 11, {
    restitution: 0.5,
    render: {
        sprite: {
            texture: imgUrl,
            xScale: 0.3,
            yScale: 0.3,  
        }
    }      
});
Preliminary answered 3/6, 2022 at 10:8 Comment(0)
T
1

You might be pushing the built-in renderer beyond its intent for simple use cases (debugging, prototyping). Consider using MJS headlessly along with a custom renderer that is better suited to a typical game or animation's rendering complexity.

You can use a similar technique as described in Matter.js Text inside a rectangle and make circles with, for example, HTML and CSS:

document.querySelector("img")
  .addEventListener("load", () => {
  const engine = Matter.Engine.create();
  const circle = {
    body: Matter.Bodies.circle(150, 0, 50),
    elem: document.querySelector("#circle"),
    render() {
      const {x, y} = this.body.position;
      this.elem.style.top = `${y - 50}px`;
      this.elem.style.left = `${x - 50}px`;
      this.elem.style.transform = `rotate(${this.body.angle}rad)`;
    },
  };
  const ground = Matter.Bodies.rectangle(
    200, 200, 400, 120, {isStatic: true}
  );
  const mouseConstraint = Matter.MouseConstraint.create(
    engine, {element: document.body}
  );
  Matter.Composite.add(
    engine.world, [circle.body, ground, mouseConstraint]
  );
  (function rerender() {
    circle.render();
    Matter.Engine.update(engine);
    requestAnimationFrame(rerender);
  })();
});
#circle {
  position: absolute;
  background: #111;
  height: 100px;
  width: 100px;
  top: -100px;
  left: -100px;
  cursor: move;
  border-radius: 50%;
}
#circle img {
  border-radius: 50%;
}

#ground {
  position: absolute;
  background: #666;
  top: 140px;
  height: 120px;
  width: 400px;
}

html, body {
  position: relative;
  height: 100%;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script>
<div id="circle">
  <img
    draggable="false"
    src="https://4.bp.blogspot.com/-DmPeZ5KQhnM/TvDXvxxb_WI/AAAAAAAAAKI/aRDOjVpBtfM/s1600/poptarticon.gif"
  >
</div>
<div id="ground"></div>

You can use the CSS background property instead of the <img> here.

Tetra answered 3/7, 2022 at 21:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.