Canvas 仅在左上象限绘图

Canvas only drawing in top left quadrant

尝试为简单的浏览器游戏创建 space 背景时,我们 运行 遇到了麻烦,因为 canvas 仅在左上象限中绘制。

这是一个在 JS 中使用 CSS 情感的 React 应用程序。我们正在尝试通过其宽度和高度 属性 来设置 canvas 维度,以依赖于此进行绘画。然后我们想使用通过情感注入的 CSS 调整 canvas 的大小以适应其容器宽度,同时保持纵横比。

可以在 https://codesandbox.io/s/epic-liskov-degs9

找到代码沙箱

有问题的组件如下所示:

/** @jsx jsx */
import { css, jsx } from "@emotion/core";
import { useEffect } from "react";
import { useRef } from "react";

// Inspired by: https://codepen.io/dudleystorey/pen/QjaXKJ
const Starfield = () => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  const drawStars = () => {
    function getRandom(min: number, max: number) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    const canvas = canvasRef.current as HTMLCanvasElement;
    if (!canvas) return;
    const context = canvas.getContext("2d");
    if (!context) return;
    const stars = 600;
    const colorrange = [0, 60, 240];
    const maxWidth = canvas.offsetWidth;
    const maxHeight = canvas.offsetHeight;
    for (var i = 0; i < stars; i++) {
      const x = Math.random() * maxWidth;
      const y = Math.random() * maxHeight;

      /**
       * x and y are what we expect but stars only show up
       * in the top left corner 
       */
      console.log(x, y);
      const radius = Math.random() * 1.2;
      const hue = colorrange[getRandom(0, colorrange.length - 1)];
      const sat = getRandom(50, 100);
      context.beginPath();
      context.arc(x, y, radius, 0, 360);
      context.fillStyle = "hsl(" + hue + ", " + sat + "%, 88%)";
      context.fill();
    }
  };
  useEffect(() => {
    drawStars();
  }, []);

  return (
    <canvas
      width="1500"
      height="1000"
      css={css`
        background: #111;
        width: 100%;
        height: auto;
      `}
      ref={canvasRef}
    ></canvas>
  );
};

export default Starfield;

您正在访问 canvas 元素的 offsetHeight 和宽度,这是 space canvas 占用的大小,而不是 canvas 的大小。您应该根据 canvas 的宽度和高度进行随机计算。将 maxWidth 和 height 更改为以下内容将使您的数字基于 canvas 尺寸而不是 DOM.

中 canvas 元素的尺寸
const maxWidth = canvas.width;
const maxHeight = canvas.height;