Search code examples
javascriptcanvassize

Am getting "Cannot set property .. which has only a getter" error (javascript canvas width)


More completely, I got:
"Cannot set property clientWidth of #<Element> which has only a getter"
(Obviously I could have had a HTML <canvas> element, but this is a minimized example of my problem.)

But I found a solution: Instead of creating elements and appending, write a string of the HTML I want and use innerHTML = string. Is there a disadvantage in doing this? Change 'true' to 'false' in the code to demo the solution:

<html>
  <head>
    <meta charset="utf-8">
    <style>
canvas { outline:1px dotted black; } 
    </style>
  </head>
  <body>
    <script>
  "use strict";
  if (true) { // this code has the error
    let elt = document.createElement('canvas');
    elt.setAttribute('id','canvas');
    elt.clientWidth = 500;
    elt.clientHeight = 500;
    document.body.appendChild(elt);
  } else {    // this has the workaround/solution
    let s = '<canvas id="canvas" width="500" height="500"></canvas>';
    document.body.innerHTML = s;
  }
  let ctx = canvas.getContext("2d");
  ctx.arc(250,250,200, 0, 6.2832);
  ctx.stroke();
    </script>
  </body>
</html>

Solution

  • The clientWidth property is a computed property which is the actual screen-width of the canvas, as determined by css and everything else. This is what the error message was trying to tell you. If you suddenly tell the browser you want the actual width to be 500px, the browser suddenly has to detemine how to get the width to be 500px via css -- and there are a LOT of css properties that affect width, and the browser doesn't know which to change. So it just disallows messing with computed properties.

    Try to set canvas.width instead. (This is what you're basically doing with the html string, setting the width and height attributes.)