Paper.js 无法正确调整 canvas 的大小

Paper.js won't resize the canvas correctly

我正在尝试 Paper.js 来找乐子,但似乎我一开始就卡住了。

resize="true" 添加到 canvas 标签应该使元素与浏览器 window 一样高和宽。然而,这样做会导致一些相当奇怪的行为。

我希望 canvas 在加载页面后立即根据视口调整自身,但它没有这样做,这就是我最初认为它根本没有调整大小的原因。然而,实际发生的事情更加奇怪:canvas 开始时其默认大小为 300x150,当我调整视口大小时,它会增长 - 缓慢但无限期 .

郑重声明,我试过使用 data-paper-resize="true"resize,或者使用 Chrome 而不是 Firefox - 都无济于事。

如果这个问题是由我这边一些莫名其妙的奇怪设置引起的,我不希望得到答案。但是,我想知道这个问题是否很普遍(或者甚至已知存在)并且有已知的原因和解决方案。

这是我使用的代码:

<!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>

将以下内容 CSS 添加到您的项目中:

<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>

我在 Github 上为此打开了一个问题,看来这是 0.9.22 中引入的错误。 @Skalkaz 向我指出了这个问题。

这是未决问题:https://github.com/paperjs/paper.js/issues/662

您也可以在等待补丁时降级到 0.9.21。

另一种选择是 - 如果您使用设定比例(相对于 body) - 覆盖纸张的视图:

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

对于仍然 运行 关注此问题的任何人,以下是我的 TypeScript/React 项目中对我有用的内容。我 运行 遇到 Paper.js 调整大小逻辑似乎与我应用程序其他地方的现有调整大小逻辑冲突/不同步的问题(也许正在进行一些数据竞争)。无论哪种方式,我都意识到可以 manually update the viewSize of the canvas.

使用 lodash debounce,可以在用户调整完 window 后使用实际 canvas 大小重新校准 Paper.js 视图。对于我的示例,我选择仅在用户调整大小 500 毫秒后执行此操作,以免在调整大小时引起性能问题,并确保所有样式都已正确更新和重新呈现。这是我找到的 TypeScript/React 示例,现在似乎运行良好:

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"
      />
  );
}