13

I'm trying to override the default canvas size that is set to: 800x600

After some digging in the documentation I found:

Matter.Render.create([options])

And the options that seem interesting are: render.options.height and render.options.width.

How do I use them correctly?

What I've tried:

(function(){
    //this is the correct reference
    var canvas = document.getElementById('canvas');
    var renderer = Matter.Render.create({
        canvas: canvas,
        height: 1000,
        width: 1000
    });
})()

Warning I'm getting:

[Matter] warn: No "render.element" passed, "render.canvas" was not inserted into document.

Which according to the docs:

render.element HTMLElement

A reference to the element where the canvas is to be inserted (if render.canvas has not been specified)

kemicofa ghost
  • 16,349
  • 8
  • 82
  • 131

1 Answers1

18

Unfortunately Matter.js doesn't have good documentation (although believe me it's an excellent engine). You are supposed to call Engine.create with an object that has a property render that has properties element and canvas. If you don't pass a canvas to this function a new canvas element is created and will be appended to the given element. Although in my test cases it seemed to still want an element as render property. It's weird I know but it gets worse...

Now if you want to set the size of the canvas you go through the main object and follow this path -> render.options.width and render.options.height so that would be something like:

{
   render: {
       options: {
           height: 1000,
           width: 1000
       }
   }
}

But the problem is that when you pass a canvas element of your own, Matter decides that the canvas height and width should be the ones that are set to the element rather than the ones the intelligent programmer is passing in options. I've filed this issue at Matter.js's GitHub repository and provided a PR with the solution but that might not be merged anytime soon. Therefore I can't really offer you a perfect solution to override this in options yet but an easy way to work around this would be to set canvas.width and canvas.height right before you init the Engine.

canvas.width = 1000;
canvas.height = 1000;

There is also an internal resize method but not any better than the option above. So in case you are really into overriding the options (maybe you are developing on top of the engine) then I suggest that you leave the canvas creation to Matter.JS by simply leaving render.canvas undefined.

Here is the full solution using canvas.width and canvas.height, note that the warning you mentioned above no longer persists and Matter.js uses the given canvas element and appends it to the given render element.

 // Matter.js module aliases
 var Engine = Matter.Engine,
   World = Matter.World,
   Body = Matter.Body,
   Bodies = Matter.Bodies,
   Composites = Matter.Composites,
   Composite = Matter.Composite,
   Constraint = Matter.Constraint,
   engine;

 (function() {

   var canvas = document.getElementById('canvas');
   var width = 1000,
     height = 1000;

   canvas.width = width;
   canvas.height = height;

   engine = Engine.create({
     render: {
       element: document.body,
       canvas: canvas,
       options: {
         width: 1000,
         height: 1000
       }
     }
   });

   // run the engine
   Engine.run(engine);

 })();
<script src="http://brm.io/js/libs/matter-js/matter-0.7.0.min.js"></script>
<canvas id="canvas"></canvas>

Edit:

If you need canvas to fill the entire page use:

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

window.addEventListener("resize", function(){
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
});

// Matter.js module aliases
var Engine = Matter.Engine,
  World = Matter.World,
  Body = Matter.Body,
  Bodies = Matter.Bodies,
  Composites = Matter.Composites,
  Composite = Matter.Composite,
  Constraint = Matter.Constraint,
  engine;

(function() {

  var canvas = document.getElementById('canvas');

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  engine = Engine.create({
    render: {
      canvas: canvas
    }
  });
  
  window.addEventListener("resize", function(){
     canvas.width = window.innerWidth;
     canvas.height = window.innerHeight;
  });

  // run the engine
  Engine.run(engine);

})();
body {
  margin: 0;
  overflow: hidden;
}
<script src="http://brm.io/js/libs/matter-js/matter-0.7.0.min.js"></script>
<canvas id="canvas"></canvas>

Edit 2: The pull request has been merged and will be available in the next edge build.

https://github.com/liabru/matter-js/issues/168

Schahriar SaffarShargh
  • 1,971
  • 2
  • 16
  • 24
  • Thank you for the insight. I'll test this later today, and get back to you. And yes the documentation could be better. Idealy I'm looking for a way to have the canvas fill the whole page rather than just a box in the webpage. – kemicofa ghost Nov 09 '15 at 08:48
  • you can set canvas.width = window.innerWidth and canvas.height = window.innerHeight – Schahriar SaffarShargh Nov 09 '15 at 08:53
  • It's not a part of the codebase. I'll report the issue and create a pull request but I doubt it will make it to the build anytime soon. As far as I am concerned this is a confusing bug. – Schahriar SaffarShargh Nov 09 '15 at 08:56
  • @Grimbode, I've fixed the issue with passed canvas width and height and created a pull request at https://github.com/liabru/matter-js/issues/168 might take some time to be merged but if you need it in the mean time you can copy the code from here https://github.com/schahriar/matter-js/commit/0b51dd67c5fadcd3919ade6b22c4c521daa61859 – Schahriar SaffarShargh Nov 09 '15 at 10:30
  • @Grimbode I've additionally made an edit to the answer to demonstrate full screen usage of canvas in Matter.js – Schahriar SaffarShargh Nov 09 '15 at 10:31
  • Works great. Just tried it. Thanks a lot. I'll give you the bounty in 21 hours. – kemicofa ghost Nov 09 '15 at 10:36
  • Is it possible to render the whole state of the engine in a smaller space than the engine exists in by downscaling it? I want to send the state of the engine to multiple clients (who will all have different screen resolutions) from a server, and have those clients render the state of the engine to their full screen. Can I do this with Matter's renderer, or do would I have to make my own? – Jonah Nov 12 '15 at 15:38
  • 1
    @ANON Although I recall that MatterJS like most engines has a scaling method I suggest using canvas.scale instead. The performance of canvas scale is much better but you will need two create two separate canvases (if you need help create a question and send me the link). http://www.w3schools.com/tags/canvas_scale.asp – Schahriar SaffarShargh Nov 12 '15 at 19:08
  • @SchahriarSaffarShargh Hi, tried this but I didn't work for me. Can you shed some lights here https://stackoverflow.com/questions/60032960/scaling-canvas-size-matter-js – Organic Heart Feb 03 '20 at 04:24