Paper.js won't resize the canvas correctly
Asked Answered
E

4

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>
Ellyellyn answered 6/3, 2015 at 9:54 Comment(6)
Try placing the scripts right before the closing </body> tagTagmeme
try after adding onResize event related code as well as specified in this link. paperjs.org/tutorials/getting-started/working-with-paper-jsAudile
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.Ellyellyn
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.Erna
@Erna 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.)Ellyellyn
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.Erna
L
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>
Lemieux answered 17/3, 2015 at 15:31 Comment(4)
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?Ellyellyn
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)Organon
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.Desai
@Lemieux how can one set canvas[resize] programmatically?Chauvin
C
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.

Curriery answered 23/3, 2015 at 15:42 Comment(3)
Ah, thanks for clearing this up. :) Nice to know I'm not the only one having that problem.Ellyellyn
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.Erna
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.Diseased
A
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"
      />
  );
}
Aerodyne answered 23/9, 2021 at 20:22 Comment(0)
C
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
Chauvin answered 4/4, 2017 at 22:32 Comment(2)
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.Extrapolate
Also the example isn't complete, no fiddle, no contextual usage within an actual code demo, no definition or example of myWidthScale or myHeightScale.Foetus

© 2022 - 2024 — McMap. All rights reserved.