Skip to content

Commit

Permalink
better packaging and ssr compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
flodlc committed Jan 28, 2022
1 parent 2911a34 commit 801eaca
Show file tree
Hide file tree
Showing 15 changed files with 257 additions and 170 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Nebula
### Nebula is a lightweight JavaScript library for creating univers animations.
### Nebula is a lightweight JavaScript library for creating univers animations with React.
Including configurable Stars, Nebulas, Comets, Planets and Suns.
Compatible with SSR

<img src="demo.jpg" />

### `Installation`
```
Expand All @@ -17,9 +21,9 @@ key | option type / notes | default
`astres` | `AstreDescription[]` | `[]`
`scale` | `number` | `1`
`speed` | `number` | `1`
`starsCount` | `number` | `150`
`starsCount` | `number` | `200`
`starsColor` | `string` | `#ffffff` (white)
`starsRotationSpeed` | `number` | `5`
`cometFrequence` | `number` | `1`
`nebulasIntensity` | `number` | `1`
`cometFrequence` | `number` | `3`
`nebulasIntensity` | `number` | `8`
`nebulasColors` | `string[]` accept rgb and hex | `["rgb(5,63,157)", "rgb(42,112,25)", "rgb(182,41,44)"]`
Binary file added demo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { smallSolarSystem } from "src/templates/smallSolarSystem";
import { bigSolarSystem } from "src/templates/bigSolarSystem";
import type { AstreDescription } from "src/astres/types";
import { ReactNebula } from "src/ReactNebula";
import { PlanetDescription, SunDescription } from "src/astres/types";

export type {AstreDescription}
export {smallSolarSystem, bigSolarSystem, ReactNebula}
type AstreDescription = PlanetDescription | SunDescription;
export type { AstreDescription };
export { smallSolarSystem, bigSolarSystem, ReactNebula };
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@flodlc/nebula",
"version": "1.0.8",
"version": "1.0.15",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
"typings": "dist/index.d.ts",
Expand Down
13 changes: 13 additions & 0 deletions src/DEFAULT_CONFIG.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AstreDescription } from "src/astres/types";

export const DEFAULT_CONFIG = {
astres: [] as AstreDescription[],
cometFrequence: 3,
scale: 1,
speed: 1,
starsCount: 200,
starsColor: "#FFFFFF",
starsRotationSpeed: 5,
nebulasIntensity: 8,
nebulasColors: ["rgb(27,2,140)", "rgb(22,91,2)", "#880554"],
};
138 changes: 48 additions & 90 deletions src/ReactNebula.tsx
Original file line number Diff line number Diff line change
@@ -1,128 +1,86 @@
import React, { useLayoutEffect, useRef, useState } from "react";
import { Planet } from "src/astres/Planet";
import { Star } from "src/astres/Star";
import { Galaxy } from "src/astres/Galaxy";
import { parseColor } from "src/utils/parseColor";
import { Sun } from "src/astres/Sun";
import { Nebula } from "src/astres/Nebula";
import { AstreDescription } from "src/astres/types";
import { Astre } from "src/astres/Astre";
import { generateStars } from "src/utils/starGenerator";
import { generateNebulas } from "src/utils/generateNebulas";
import { generateComet } from "src/utils/generateComet";
import { SystemConfig } from "src/types";

const DEFAULT_CONFIG = {
astres: [] as AstreDescription[],
cometFrequence: 1,
scale: 0.8,
speed: 0.3,
starsCount: 150,
starsColor: "#FFFFFF",
starsRotationSpeed: 5,
nebulasIntensity: 6,
nebulasColors: ["rgb(5,63,157)", "rgb(42,112,25)", "rgb(182,41,44)"],
};
import { DEFAULT_CONFIG } from "src/DEFAULT_CONFIG";
import { drawAstres } from "src/draw";

export const ReactNebula = ({ config = {} }: { config?: SystemConfig }) => {
const filledConfig = Object.assign({}, DEFAULT_CONFIG, config);
const canvasRef = useRef<HTMLCanvasElement>(null);
const [iter, setIter] = useState(0);
const bgCanvasRef = useRef<HTMLCanvasElement>(null);
const wrapperRef = useRef<HTMLDivElement>(null);
const [size, setSize] = useState({ height: 0, width: 0 });

useLayoutEffect(() => {
const handler = () => {
setIter(iter + 1);
setSize({
height: wrapperRef.current?.offsetHeight ?? 0,
width: wrapperRef.current?.offsetWidth ?? 0,
});
};
if (!window) return;
handler();
if (typeof window === "undefined") return;
window.addEventListener("resize", handler);
return () => {
window.removeEventListener("resize", handler);
};
}, [iter]);
}, [setSize]);

useLayoutEffect(() => {
if (!canvasRef.current) return;
const canvas = canvasRef.current;

const width = canvas.width;
const height = canvas.height;

const ctx = canvas.getContext("2d");
if (!ctx) return;

const planets: Record<string, Astre> = {};
return drawAstres({
astresConfig: [
...generateStars({
rotationSpeed: filledConfig.starsRotationSpeed,
count: filledConfig.starsCount,
color: filledConfig.starsColor,
}),
...generateComet({
frequence: filledConfig.cometFrequence,
}),
...filledConfig.astres,
],
config: filledConfig,
canvas: canvasRef.current as HTMLCanvasElement,
play: true,
});
}, [size]);

const astres = [
...generateStars({
rotationSpeed: filledConfig.starsRotationSpeed,
count: filledConfig.starsCount,
color: filledConfig.starsColor,
}),
...generateNebulas({
useLayoutEffect(() => {
return drawAstres({
astresConfig: generateNebulas({
intensity: filledConfig.nebulasIntensity,
colors: filledConfig.nebulasColors,
}),
...generateComet({
frequence: filledConfig.cometFrequence,
}),
...filledConfig.astres,
];

astres.forEach((astreConfig) => {
const Type = {
star: Star,
galaxy: Galaxy,
planet: Planet,
sun: Sun,
nebula: Nebula,
}[astreConfig.type];
planets[astreConfig.name] = new Type({
ctx,
...astreConfig,
distance: astreConfig.distance * filledConfig.scale,
rgb: parseColor(astreConfig.color),
width: astreConfig.width * filledConfig.scale,
origin: astreConfig.origin ? planets[astreConfig.origin] : undefined,
rotateSpeed: astreConfig.rotateSpeed * filledConfig.speed,
});
config: filledConfig,
canvas: bgCanvasRef.current as HTMLCanvasElement,
play: false,
bgColor: "rgb(8, 8, 8)",
});
}, [size]);

ctx.save();

let animation: number | undefined;
const drawCtx = () => {
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "rgb(8, 8, 8)";
ctx.fillRect(0, 0, width, height);
Object.values(planets).forEach((planet) => planet.draw());
animation = requestAnimationFrame(drawCtx);
};

drawCtx();

return () => {
ctx.restore();
if (animation) {
cancelAnimationFrame(animation);
}
};
}, [iter]);

if (!window) return <div></div>;
return (
<div
ref={wrapperRef}
style={{
overflow: "hidden",
background: "#0a1929",
height: "100%",
width: "100%",
position: "relative",
position: "absolute",
}}
>
<canvas
width={window.innerWidth}
height={window.innerHeight}
style={{ height: "100%", width: "100%" }}
width={size.width * 2}
height={size.height * 2}
style={{ height: "100%", width: "100%", position: "absolute" }}
ref={bgCanvasRef}
/>
<canvas
width={size.width * 2}
height={size.height * 2}
style={{ height: "100%", width: "100%", position: "absolute" }}
ref={canvasRef}
/>
</div>
Expand Down
13 changes: 10 additions & 3 deletions src/astres/Nebula.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Astre } from "src/astres/Astre";
import { Drawable } from "src/astres/types";

export class Nebula extends Astre {
intensity: number;

constructor({
ctx,
width,
Expand All @@ -10,6 +12,7 @@ export class Nebula extends Astre {
rgb,
origin,
startAngle = Math.random() * 360,
intensity,
}: {
ctx: CanvasRenderingContext2D;
width: number;
Expand All @@ -19,6 +22,7 @@ export class Nebula extends Astre {
origin?: Drawable;
invisible?: boolean;
startAngle?: number;
intensity: number;
}) {
super({
ctx,
Expand All @@ -29,12 +33,13 @@ export class Nebula extends Astre {
distance,
rotateSpeed,
});
this.intensity = intensity;
}

draw() {
this.rotate();
this.ctx.beginPath();
this.ctx.arc(...this.getOriginCoords(), this.width * 10, 0, Math.PI * 2);
this.ctx.arc(...this.getOriginCoords(), this.width * 7, 0, Math.PI * 2);
this.ctx.closePath();
this.ctx.shadowBlur = 0;

Expand All @@ -44,11 +49,13 @@ export class Nebula extends Astre {
originCoords[1],
0,
...originCoords,
this.width * 10
this.width * 7
);
gradient.addColorStop(
0,
`rgba(${this.rgb[0]}, ${this.rgb[1]}, ${this.rgb[2]}, 0.038)`
`rgba(${this.rgb[0]}, ${this.rgb[1]}, ${this.rgb[2]}, ${
this.intensity / 100
})`
);
gradient.addColorStop(
1,
Expand Down
35 changes: 33 additions & 2 deletions src/astres/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
export type AstreDescription = {
export type NubulaDescription = {
type: "nebula";
intensity?: number;
} & BaseAstreDescription;

export type PlanetDescription = {
type: "planet";
intensity?: number;
} & BaseAstreDescription;

export type SunDescription = {
type: "sun";
intensity?: number;
} & BaseAstreDescription;

export type StarDescription = {
type: "star";
intensity?: number;
} & BaseAstreDescription;

export type GalaxyDescription = {
type: "galaxy";
intensity?: number;
} & BaseAstreDescription;

type BaseAstreDescription = {
name: string;
type: "galaxy" | "star" | "planet" | "sun" | "nebula";
width: number;
rotateSpeed: number;
distance: number;
Expand All @@ -9,6 +33,13 @@ export type AstreDescription = {
startAngle?: number;
};

export type AstreDescription =
| NubulaDescription
| PlanetDescription
| SunDescription
| StarDescription
| GalaxyDescription;

export interface Drawable {
draw: () => void;
getOriginCoords: () => [number, number];
Expand Down
Loading

0 comments on commit 801eaca

Please sign in to comment.