1

How do i gradient fill a body created in matter.js?

I have tried this but it won't work:

Bodies.rectangle(400, 520, 800, 120, { render: { fillStyle: 'linear-gradient(50%, red, blue)' } );
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Yaume
  • 198
  • 1
  • 6
  • Use your own renderer such as plain DOM, canvas or p5.js, then you can do whatever you want. MJS' builtin renderer is just for proofs of concept -- MJS' primary role is a headless physics engine, not a full-featured rendering suite. See [Using Matter.js to render to the DOM or React](https://stackoverflow.com/questions/63906218/using-matter-js-to-render-to-the-dom-or-react/65354225#65354225) and simply apply your desired CSS to the DOM elements. – ggorlen Jun 29 '21 at 15:53
  • Thanks for the directions, but i'd need a little more specific piece of code to understand how to use it with plain js (so i would'nt need React) and create my own renderer – Yaume Jul 05 '21 at 07:29
  • No React necessary. Use the top code block in the link (plain JS) but change the CSS `background` property on one or both of the elements to `linear-gradient(45deg, blue, red);` -- that's it. – ggorlen Jul 05 '21 at 13:30

1 Answers1

1

MJS is a physics engine, not a rendering library. The built-in renderer is there for prototyping purposes only. As indicated in the comments, your use case sounds complex enough that you've outgrown the built-in renderer. I'd suggest refactoring to use canvas, the DOM or any other rendering library that suits your fancy.

If you want to use the DOM, take this answer and simply change background: #666; to background: linear-gradient(45deg, blue, red);.

If you want to use HTML5 canvas, here's an example:

const renderVertices = body => {
  ctx.beginPath();
  body.vertices.forEach(({x, y}) => ctx.lineTo(x, y));
  ctx.closePath();
  ctx.fill();
  ctx.stroke();
};

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const gradient = ctx.createLinearGradient(
  0, 0, canvas.width, canvas.height
);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
ctx.fillStyle = gradient;
ctx.lineWidth = 2;

const engine = Matter.Engine.create();  
const box = Matter.Bodies.rectangle(150, 0, 40, 40);
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, [box, ground, mouseConstraint]
);

(function rerender() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  renderVertices(box);
  renderVertices(ground);
  Matter.Engine.update(engine);
  requestAnimationFrame(rerender);
})();
body {
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<canvas width="700" height="400"></canvas>

Once you're comfortable with a headless setup, adapting to another rendering library is straightforward.

ggorlen
  • 44,755
  • 7
  • 76
  • 106