Matter
yarn add matter-attractors matter-js matter-wrap
Physics engine on canvas
import React, { useState, useEffect, useContext, useRef } from "react";
import ReactDOM from "react-dom";
import Matter from "matter-js";
import MatterAttractors from "matter-attractors";
import MatterWrap from "matter-wrap";
import PropTypes from "prop-types";
import { randomColor } from "src/utils/helpers";
import { isMobile } from "src/utils/utils";
const debug = require("debug")("app:LandingViz");
let BALL_COUNT = 150;
if (isMobile) BALL_COUNT = 50;
const BALL_MIN_RADIUS = 10;
const BALL_MAX_RADIUS = 16;
const BALL_SPEED = 1;
const Engine = Matter.Engine,
Render = Matter.Render,
World = Matter.World,
Body = Matter.Body,
Bodies = Matter.Bodies,
Mouse = Matter.Mouse,
Vector = Matter.Vector,
Runner = Matter.Runner,
Common = Matter.Common,
Composite = Matter.Composite,
MouseConstraint = Matter.MouseConstraint;
Matter.use(MatterAttractors);
Matter.use(MatterWrap);
MatterAttractors.Attractors.gravityConstant = 0.0001;
export default function LandingViz(props) {
const tableRef = useRef(null);
function addCircles(world, render) {
for (let i = 0; i < BALL_COUNT; i++) {
const radius = Common.random(BALL_MIN_RADIUS, BALL_MAX_RADIUS);
const body = Bodies.circle(
Common.random(BALL_MIN_RADIUS, render.options.width),
Common.random(BALL_MIN_RADIUS, render.options.height),
radius,
{
mass: Common.random(BALL_MIN_RADIUS, BALL_MAX_RADIUS),
frictionAir: 0,
render: {
fillStyle: randomColor(),
// strokeStyle: "#FFFFFF",
},
plugin: {
attractors: [
// there is a built in helper function for Newtonian gravity!
// you can find out how it works in index.js
MatterAttractors.Attractors.gravity,
],
wrap: {
min: { x: 0, y: 0 },
max: { x: render.options.width, y: render.options.height },
},
},
}
);
Body.setVelocity(body, {
x: Common.random(-BALL_SPEED, BALL_SPEED),
y: Common.random(-BALL_SPEED, BALL_SPEED),
});
World.add(world, body);
}
}
useEffect(() => {
setTimeout(() => {
const CANVAS_WIDTH = tableRef.current.clientWidth;
const CANVAS_HEIGHT = tableRef.current.clientHeight;
const engine = Engine.create();
engine.world.gravity.scale = 0;
const render = Render.create({
element: tableRef.current,
engine: engine,
options: {
width: CANVAS_WIDTH,
height: CANVAS_HEIGHT,
background: "transparent",
wireframes: false,
},
});
const runner = Runner.create();
Runner.run(runner, engine);
Render.run(render);
addCircles(engine.world, render);
// // add mouse control
// const mouse = Mouse.create(render.canvas),
// mouseConstraint = MouseConstraint.create(engine, {
// mouse: mouse,
// constraint: {
// stiffness: 0.2,
// render: {
// visible: false,
// },
// },
// });
// World.add(engine.world, mouseConstraint);
// Matter.Events.on(mouseConstraint, "mousedown", function (event) {
// addCircle(engine.world);
// });
// mouseConstraint.mouse.element.removeEventListener(
// "mousewheel",
// mouseConstraint.mouse.mousewheel
// );
// mouseConstraint.mouse.element.removeEventListener(
// "DOMMouseScroll",
// mouseConstraint.mouse.mousewheel
// );
Engine.run(engine);
return () => {
Matter.Render.stop(render);
Matter.Runner.stop(runner);
};
}, 1500);
}, []);
return <div className="w-full h-full" ref={tableRef} />;
}
Last updated