Skip to content

Animating in React #137

@rrriki

Description

@rrriki

Hi @mattdesl,

I'm trying to create an animated sketch using React. But I'm not really sure how I can accomplish that with the way I've set up things.

I have my own Canvas component which wraps your canvasSketch, basically based off the example for React in the Docs.

import React, { useEffect, useRef } from "react";
import styled from "styled-components";
// @ts-ignore
import canvasSketch from "canvas-sketch";

export type CanvasDrawingProps = {
  context: CanvasRenderingContext2D;
  width: number;
  height: number;
};

const StyledCanvas = styled.canvas`
  background-color: #e1e3df;
  &:hover {
    filter: hue-rotate(90deg);
  }
`;

const WIDTH = 400;
const HEIGHT = 400;

interface CanvasProps {
  draw: (props: CanvasDrawingProps) => void;
  animate?: boolean;
}

export const Canvas: React.FC<CanvasProps> = (props) => {
  const { draw, animate } = props;
  const ref = useRef<HTMLCanvasElement | null>(null);

  useEffect(() => {
    console.log("running canvas useEffect");

    canvasSketch(draw, {
      dimensions: [WIDTH, HEIGHT],
      units: "px",
      resizeCanvas: false,
      styleCanvas: true,
      scaleToView: false,
      canvas: ref.current,
      animate,
    });

    return function cleanUp() {
      console.log("Canvas unmounting");
    };
  }, [draw, animate]);

  return (
    <StyledCanvas
      id="canvas"
      ref={ref}
      {...props}
      width={WIDTH}
      height={HEIGHT}
    />
  );
};

And I'm using it in another component which passes the draw method I want to be call per frame.

import React from "react";
import { Canvas, CanvasDrawingProps } from "../components";
import { Agent, randomHexColor, randomInRange } from "../utils";

export const Agents: React.FC = () => {
  const drawAgents = ({ context, width, height }: CanvasDrawingProps) => {
    const agentsCount = 40;

    for (let i = 0; i <= agentsCount; i++) {
      const radius = randomInRange(1, 13);
      const agent = new Agent(0, 0, radius);

      agent.setStrokeColor(randomHexColor());
      agent.setFillColor(randomHexColor());
      agent.setLineWidth(randomInRange(1, 5));
      const x = randomInRange(0, width);
      const y = randomInRange(0, height);
      agent.updatePosition({x, y});

      agent.draw(context);
    }
  };

  return <Canvas draw={drawAgents} animate={true} />;
};

But it seems that React will not re-render since the no props or state change and the useEffect won't be run again since the dependencies don't really change.

Here's the pull request where I'm trying to add this particular example.

Is this the right way to set this up? Or should I be tapping into the requestAnimationFrame of the canvas some other way?

I'd appreciate any input you have, also I wanted thank you and say say I'm a huge fan of your work both technically and artistically 🙌🏻

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions