Reputation: 591
Trying to create a space background for a simple browser game we are running into trouble with the canvas only painting in the top left quadrant.
This is a React app using Emotion as CSS in JS. We are trying to set the canvas dimension via its width and height property to rely on this for painting. Then we want to use CSS injected through emotion to resize the canvas to fit its containers width while maintaining aspect ratio.
A code sandbox can be found at https://codesandbox.io/s/epic-liskov-degs9
The component in question looks like this:
/** @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;
Upvotes: 0
Views: 353
Reputation: 8366
You're accessing the offsetHeight and width of the canvas element which is how much space the canvas takes up not the size of the canvas. What you should be basing your random calculation on is the width and height of the canvas. Changing maxWidth and height to the following will base your numbers off the canvas dimensions not the dimensions of the canvas element in the DOM.
const maxWidth = canvas.width;
const maxHeight = canvas.height;
Upvotes: 1