31

I'm trying out Paper.js for fun, but it seems I'm already stuck at the very start.

Adding resize="true" to the canvas tag is supposed to make the element as high and wide as the browser window. However, doing that results in some rather strange behavior.

I expected the canvas to adjust itself to the viewport right after loading the page, but it didn't do so, which is why I initially thought it didn't resize at all. What actually happens, though, is even more bizarre: The canvas starts out at its default size of 300x150, and when I resize the viewport, it grows - slowly, but indefinitely.

For the record, I've tried using data-paper-resize="true" or just resize instead, or using Chrome instead of Firefox - all to no avail.

I'm not expecting an answer if this problem is caused by some inexplicably weird setup on my end. I am wondering, however, if the problem is common (or even known to exist at all) and has known causes and solutions.

Here's the code I'm using:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="paper-full.min.js"></script>
        <script type="text/paperscript" canvas="myCanvas">

            var path = new Path();
            path.strokeColor = 'black';
            path.moveTo(new Point(120, 120));
            path.lineTo(new Point(500, 500));

        </script>
    </head>
    <body>
        <canvas id="myCanvas" style="border: 1px dotted red;" resize="true"></canvas>
    </body>
</html>
vvye
  • 1,208
  • 1
  • 10
  • 25
  • Try placing the scripts right before the closing

    tag

    – Jonas Grumann Mar 06 '15 at 09:56
  • try after adding onResize event related code as well as specified in this link. http://paperjs.org/tutorials/getting-started/working-with-paper-js/ – K D Mar 06 '15 at 10:01
  • I'm afraid neither suggestion did anything. I've just noticed, though, that the canvas actually does change its size, just not in the way I expect it to - see the updated question. – vvye Mar 06 '15 at 10:13
  • 1
    It would be good for you to accept the answer that fixed your problem. It's a useful answer to a common problem and the person took time to provide it. – bmacnaughton Jan 07 '16 at 15:49
  • @bmacnaughton Fair enough, I'm just not sure which one to accept. 3337813's answer provides a useful workaround, while ngryman provides insight by explaining that it's actually a bug and the workaround isn't what you're intended to do. Any advice/best practice? (I've already upvoted both, by the way.) – vvye Jan 07 '16 at 17:35
  • I'm honestly not sure best practice. But the second one apparently solved your issue while the first said wait for a patch. I'd vote for utility. – bmacnaughton Jan 07 '16 at 17:40

4 Answers4

32

Add the following CSS to your project:

<style type="text/css">
html,
body {
    margin: 0;
    overflow: hidden;
    height: 100%;
}

/* Scale canvas with resize attribute to full size */
canvas[resize] {
    width: 100%;
    height: 100%;
}
</style>
user3337813
  • 466
  • 4
  • 4
  • 1
    Looks like that did it! I wonder why that CSS is necessary, though (as in, something the user has to handle), and why the docs don't seem to mention it. Does anyone who wants a full-size canvas in Paper.js have to add those styles manually? – vvye Mar 17 '15 at 16:12
  • I needed the full width only, so `canvas[resize] { width: 100%; height: 600px; }` did it for me. Thanks!!! (I'm using Paper.js 0.9.22) – Marcel Mar 27 '15 at 16:55
  • 1
    Using overflow: hidden will likely lead to trouble later on. Set canvas to display: block instead and you can remove the overflow without getting scrollbars. – Emil Stenström Dec 26 '15 at 12:36
  • @user3337813 how can one set canvas[resize] programmatically? – SumNeuron Apr 05 '17 at 15:07
9

I opened an issue for this on Github and it seems that this is a bug introduced in 0.9.22. @Skalkaz pointed me this question.

Here is the pending issue: https://github.com/paperjs/paper.js/issues/662.

You can also downgrade to 0.9.21 while waiting for a patch.

ngryman
  • 7,112
  • 2
  • 26
  • 23
  • 1
    Ah, thanks for clearing this up. :) Nice to know I'm not the only one having that problem. – vvye Mar 23 '15 at 21:56
  • Following the github issue this is not going to be fixed, so waiting on a patch is not a viable alternative. Details are in the issue, but the author believes that canvas sizing is a CSS task, not a paper task. I think he's right. – bmacnaughton Jan 07 '16 at 15:51
  • For future folks running into the same problem - the library author knows this is an issue, but hasn't had a chance to update the documentation to include the need for CSS now. – Peter Recore Mar 14 '16 at 18:42
1

For anybody still running into this issue, here's what worked for me in my TypeScript/React project. I was running into issues where the Paper.js resize logic seemed to be conflicting / getting out of sync with existing resize logic I had elsewhere in my app (perhaps some data races were going on). Either way, I realized it's possible to manually update the viewSize of the canvas.

Using lodash debounce, it's possible to re-calibrate the Paper.js view with the actual canvas size once the user is done resizing their window. For my example, I chose to only do this once the user had been done resizing for 500ms, so as not to cause performance issues while resizing and to also make sure that all styles had already been correctly updated and re-rendered. Here's the TypeScript/React example I landed on that seems to be working fine now:

export default function ChalkboardCanvas() {

// get a direct reference to the canvas element
const canvasRef = useRef(null);

 /** 
  * Sometimes the Paper.js view gets out of sync when resizing
  * manually update it instead once the user is done resizing 
  */
  const onResize = useCallback(debounce(() => {
    if (canvasRef.current) {
      const { width, height } = canvasRef.current.getBoundingClientRect();
      paper.view.viewSize = new paper.Size(width, height);
    }
  }, 500, {
    leading: false,
    trailing: true,
  }), []);

  useEffect(() => {
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [onResize]);

return (
     <canvas
        style={{
          width: '100%',
          height: '100%',
        }}
        ref={canvasRef}
        resize="true"
      />
  );
}
Austin Theriot
  • 256
  • 2
  • 5
0

Another option is - if you are using set proportions (relative to the body) - to override paper's view:

var pageWidth = document.getElementsByTagName("BODY")[0].clientWidth
var pageHeight = document.getElementsByTagName("BODY")[0].clientHeight
view.size.width = pageWidth * myWidthScale
view.size.height = pageHeight * myHeightScale
center = new Point(width / 2, pageHeight / 2)
view.center = center
SumNeuron
  • 4,850
  • 5
  • 39
  • 107
  • 1
    I would not do this as it will only work once and not if the window is resized. it is also bound to body and won't work on any other element in the DOM. – Nathan Jul 20 '17 at 18:00
  • Also the example isn't complete, no fiddle, no contextual usage within an actual code demo, no definition or example of `myWidthScale` or `myHeightScale`. – Steven Grimaldo Feb 04 '22 at 21:11