git-hash-art 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.release-it.json +1 -1
- package/CHANGELOG.md +15 -0
- package/dist/main.js +262 -155
- package/dist/main.js.map +1 -1
- package/dist/module.js +261 -154
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -0
- package/global.d.ts +12 -0
- package/package.json +15 -11
- package/src/{index.js → index.ts} +36 -31
- package/src/lib/canvas/{colors.js → colors.ts} +53 -11
- package/src/lib/canvas/{draw.js → draw.ts} +29 -11
- package/src/lib/canvas/shapes/{basic.js → basic.ts} +14 -12
- package/src/lib/canvas/shapes/{complex.js → complex.ts} +118 -34
- package/src/lib/canvas/shapes/{index.js → index.ts} +7 -1
- package/src/lib/canvas/shapes/sacred.ts +206 -0
- package/src/lib/canvas/shapes/utils.ts +65 -0
- package/src/lib/{constants.js → constants.ts} +32 -5
- package/src/lib/{utils.js → utils.ts} +34 -6
- package/tsconfig.json +16 -0
- package/eslint.config.mjs +0 -29
- package/src/lib/canvas/shapes/sacred.js +0 -173
- package/src/lib/canvas/shapes/utils.js +0 -37
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ColorScheme from "color-scheme";
|
|
2
|
-
import
|
|
2
|
+
import "../../../global.d";
|
|
3
3
|
|
|
4
|
+
import { gitHashToSeed } from "../utils";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Generates a color scheme based on a given Git hash.
|
|
@@ -8,7 +9,7 @@ import { gitHashToSeed } from "../utils";
|
|
|
8
9
|
* @param {string} gitHash - The Git hash used to generate the color scheme.
|
|
9
10
|
* @returns {string[]} An array of hex color codes representing the generated color scheme.
|
|
10
11
|
*/
|
|
11
|
-
export function generateColorScheme(gitHash) {
|
|
12
|
+
export function generateColorScheme(gitHash: string): string[] {
|
|
12
13
|
const seed = gitHashToSeed(gitHash);
|
|
13
14
|
const scheme = new ColorScheme();
|
|
14
15
|
scheme
|
|
@@ -16,7 +17,7 @@ export function generateColorScheme(gitHash) {
|
|
|
16
17
|
.scheme("analogic")
|
|
17
18
|
.variation("soft");
|
|
18
19
|
|
|
19
|
-
let colors = scheme.colors().map((hex) => `#${hex}`);
|
|
20
|
+
let colors = scheme.colors().map((hex: string) => `#${hex}`);
|
|
20
21
|
|
|
21
22
|
const contrastingHue = (seed + 180) % 360;
|
|
22
23
|
const contrastingScheme = new ColorScheme();
|
|
@@ -26,30 +27,69 @@ export function generateColorScheme(gitHash) {
|
|
|
26
27
|
return colors;
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
interface MetallicColors {
|
|
31
|
+
gold: string;
|
|
32
|
+
silver: string;
|
|
33
|
+
copper: string;
|
|
34
|
+
bronze: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface SacredPalette {
|
|
38
|
+
primary: string;
|
|
39
|
+
secondary: string;
|
|
40
|
+
accent: string;
|
|
41
|
+
metallic: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ElementalPalette {
|
|
45
|
+
earth: string;
|
|
46
|
+
water: string;
|
|
47
|
+
air: string;
|
|
48
|
+
fire: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface ChakraPalette {
|
|
52
|
+
root: string;
|
|
53
|
+
sacral: string;
|
|
54
|
+
solar: string;
|
|
55
|
+
heart: string;
|
|
56
|
+
throat: string;
|
|
57
|
+
third_eye: string;
|
|
58
|
+
crown: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
type ColorPalette = SacredPalette | ElementalPalette | ChakraPalette | string[];
|
|
62
|
+
|
|
29
63
|
// Enhanced color scheme generation for sacred geometry
|
|
30
64
|
export class SacredColorScheme {
|
|
31
|
-
|
|
65
|
+
private seed: number;
|
|
66
|
+
public baseScheme: string[];
|
|
67
|
+
private complementaryScheme: string[];
|
|
68
|
+
private metallic: MetallicColors;
|
|
69
|
+
|
|
70
|
+
constructor(gitHash: string) {
|
|
32
71
|
this.seed = this.gitHashToSeed(gitHash);
|
|
33
72
|
this.baseScheme = this.generateBaseScheme();
|
|
34
73
|
this.complementaryScheme = this.generateComplementaryScheme();
|
|
35
74
|
this.metallic = this.generateMetallicColors();
|
|
36
75
|
}
|
|
37
76
|
|
|
38
|
-
gitHashToSeed(hash) {
|
|
77
|
+
private gitHashToSeed(hash: string): number {
|
|
39
78
|
return parseInt(hash.slice(0, 8), 16);
|
|
40
79
|
}
|
|
41
80
|
|
|
42
|
-
generateBaseScheme() {
|
|
81
|
+
private generateBaseScheme(): string[] {
|
|
43
82
|
const scheme = new ColorScheme();
|
|
83
|
+
scheme;
|
|
44
84
|
return scheme
|
|
45
85
|
.from_hue(this.seed % 360)
|
|
46
86
|
.scheme("analogic")
|
|
47
87
|
.variation("soft")
|
|
48
88
|
.colors()
|
|
49
|
-
.map((hex) => `#${hex}`);
|
|
89
|
+
.map((hex: string) => `#${hex}`);
|
|
50
90
|
}
|
|
51
91
|
|
|
52
|
-
generateComplementaryScheme() {
|
|
92
|
+
private generateComplementaryScheme(): string[] {
|
|
53
93
|
const complementaryHue = (this.seed + 180) % 360;
|
|
54
94
|
const scheme = new ColorScheme();
|
|
55
95
|
return scheme
|
|
@@ -57,10 +97,10 @@ export class SacredColorScheme {
|
|
|
57
97
|
.scheme("mono")
|
|
58
98
|
.variation("soft")
|
|
59
99
|
.colors()
|
|
60
|
-
.map((hex) => `#${hex}`);
|
|
100
|
+
.map((hex: string) => `#${hex}`);
|
|
61
101
|
}
|
|
62
102
|
|
|
63
|
-
generateMetallicColors() {
|
|
103
|
+
private generateMetallicColors(): MetallicColors {
|
|
64
104
|
return {
|
|
65
105
|
gold: "#FFD700",
|
|
66
106
|
silver: "#C0C0C0",
|
|
@@ -69,7 +109,9 @@ export class SacredColorScheme {
|
|
|
69
109
|
};
|
|
70
110
|
}
|
|
71
111
|
|
|
72
|
-
getColorPalette(
|
|
112
|
+
getColorPalette(
|
|
113
|
+
type: "sacred" | "elemental" | "chakra" | "default" = "sacred",
|
|
114
|
+
): ColorPalette {
|
|
73
115
|
switch (type) {
|
|
74
116
|
case "sacred":
|
|
75
117
|
return {
|
|
@@ -1,17 +1,29 @@
|
|
|
1
|
-
import { PatternCombiner } from "../utils";
|
|
1
|
+
import { PatternCombiner, ProportionType } from "../utils";
|
|
2
2
|
import { shapes } from "./shapes";
|
|
3
3
|
|
|
4
|
+
interface DrawShapeConfig {
|
|
5
|
+
fillColor: string;
|
|
6
|
+
strokeColor: string;
|
|
7
|
+
strokeWidth: number;
|
|
8
|
+
size: number;
|
|
9
|
+
rotation: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface EnhanceShapeConfig extends DrawShapeConfig {
|
|
13
|
+
patterns?: Array<{ type: string; config: any }>;
|
|
14
|
+
proportionType?: ProportionType;
|
|
15
|
+
baseOpacity?: number;
|
|
16
|
+
opacityReduction?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
4
19
|
export function drawShape(
|
|
5
|
-
ctx,
|
|
6
|
-
shape,
|
|
7
|
-
x,
|
|
8
|
-
y,
|
|
9
|
-
|
|
10
|
-
strokeColor,
|
|
11
|
-
strokeWidth,
|
|
12
|
-
size,
|
|
13
|
-
rotation
|
|
20
|
+
ctx: CanvasRenderingContext2D,
|
|
21
|
+
shape: string,
|
|
22
|
+
x: number,
|
|
23
|
+
y: number,
|
|
24
|
+
config: DrawShapeConfig,
|
|
14
25
|
) {
|
|
26
|
+
const { fillColor, strokeColor, strokeWidth, size, rotation } = config;
|
|
15
27
|
ctx.save();
|
|
16
28
|
ctx.translate(x, y);
|
|
17
29
|
ctx.rotate((rotation * Math.PI) / 180);
|
|
@@ -30,7 +42,13 @@ export function drawShape(
|
|
|
30
42
|
}
|
|
31
43
|
|
|
32
44
|
// Integration with existing generation logic
|
|
33
|
-
export function enhanceShapeGeneration(
|
|
45
|
+
export function enhanceShapeGeneration(
|
|
46
|
+
ctx: CanvasRenderingContext2D,
|
|
47
|
+
shape: string,
|
|
48
|
+
x: number,
|
|
49
|
+
y: number,
|
|
50
|
+
config: EnhanceShapeConfig,
|
|
51
|
+
) {
|
|
34
52
|
const {
|
|
35
53
|
fillColor,
|
|
36
54
|
strokeColor,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
type DrawFunction = (ctx: CanvasRenderingContext2D, size: number) => void;
|
|
2
|
+
|
|
3
|
+
export const drawCircle: DrawFunction = (ctx, size) => {
|
|
2
4
|
ctx.beginPath();
|
|
3
5
|
ctx.arc(0, 0, size / 2, 0, Math.PI * 2);
|
|
4
6
|
};
|
|
5
7
|
|
|
6
|
-
export const drawSquare = (ctx, size) => {
|
|
8
|
+
export const drawSquare: DrawFunction = (ctx, size) => {
|
|
7
9
|
ctx.beginPath();
|
|
8
10
|
ctx.rect(-size / 2, -size / 2, size, size);
|
|
9
11
|
};
|
|
10
12
|
|
|
11
|
-
export const drawTriangle = (ctx, size) => {
|
|
13
|
+
export const drawTriangle: DrawFunction = (ctx, size) => {
|
|
12
14
|
ctx.beginPath();
|
|
13
15
|
ctx.moveTo(0, -size / 2);
|
|
14
16
|
ctx.lineTo(-size / 2, size / 2);
|
|
@@ -16,7 +18,7 @@ export const drawTriangle = (ctx, size) => {
|
|
|
16
18
|
ctx.closePath();
|
|
17
19
|
};
|
|
18
20
|
|
|
19
|
-
export const drawHexagon = (ctx, size) => {
|
|
21
|
+
export const drawHexagon: DrawFunction = (ctx, size) => {
|
|
20
22
|
ctx.beginPath();
|
|
21
23
|
for (let i = 0; i < 6; i++) {
|
|
22
24
|
const angle = (Math.PI / 8) * i;
|
|
@@ -28,7 +30,7 @@ export const drawHexagon = (ctx, size) => {
|
|
|
28
30
|
ctx.closePath();
|
|
29
31
|
};
|
|
30
32
|
|
|
31
|
-
export const drawStar = (ctx, size) => {
|
|
33
|
+
export const drawStar: DrawFunction = (ctx, size) => {
|
|
32
34
|
ctx.beginPath();
|
|
33
35
|
for (let i = 0; i < 10; i++) {
|
|
34
36
|
const angle = Math.PI / 5 + (Math.PI / 5) * i * 3;
|
|
@@ -41,7 +43,7 @@ export const drawStar = (ctx, size) => {
|
|
|
41
43
|
ctx.closePath();
|
|
42
44
|
};
|
|
43
45
|
|
|
44
|
-
export const drawJackedStar = (ctx, size) => {
|
|
46
|
+
export const drawJackedStar: DrawFunction = (ctx, size) => {
|
|
45
47
|
ctx.beginPath();
|
|
46
48
|
for (let i = 0; i < 10; i++) {
|
|
47
49
|
const angle = Math.PI / 30 + (Math.PI / 30) * i * 8;
|
|
@@ -54,14 +56,14 @@ export const drawJackedStar = (ctx, size) => {
|
|
|
54
56
|
ctx.closePath();
|
|
55
57
|
};
|
|
56
58
|
|
|
57
|
-
export const drawHeart = (ctx, size) => {
|
|
59
|
+
export const drawHeart: DrawFunction = (ctx, size) => {
|
|
58
60
|
ctx.beginPath();
|
|
59
61
|
ctx.moveTo(0, size / 4);
|
|
60
62
|
ctx.quadraticCurveTo(size / 2, size / 4, 0, -size / 4);
|
|
61
63
|
ctx.quadraticCurveTo(-size / 2, size / 4, 0, size / 4);
|
|
62
64
|
};
|
|
63
65
|
|
|
64
|
-
export const drawDiamond = (ctx, size) => {
|
|
66
|
+
export const drawDiamond: DrawFunction = (ctx, size) => {
|
|
65
67
|
ctx.beginPath();
|
|
66
68
|
ctx.moveTo(0, -size / 2);
|
|
67
69
|
ctx.lineTo(size / 2, 0);
|
|
@@ -70,7 +72,7 @@ export const drawDiamond = (ctx, size) => {
|
|
|
70
72
|
ctx.closePath();
|
|
71
73
|
};
|
|
72
74
|
|
|
73
|
-
export const drawCube = (ctx, size) => {
|
|
75
|
+
export const drawCube: DrawFunction = (ctx, size) => {
|
|
74
76
|
ctx.beginPath();
|
|
75
77
|
ctx.moveTo(-size / 2, -size / 2);
|
|
76
78
|
ctx.lineTo(size / 2, -size / 2);
|
|
@@ -80,7 +82,7 @@ export const drawCube = (ctx, size) => {
|
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
// Optional: Create a shape map for easier lookup
|
|
83
|
-
export const basicShapes = {
|
|
85
|
+
export const basicShapes: Record<string, DrawFunction> = {
|
|
84
86
|
circle: drawCircle,
|
|
85
87
|
square: drawSquare,
|
|
86
88
|
triangle: drawTriangle,
|
|
@@ -89,5 +91,5 @@ export const basicShapes = {
|
|
|
89
91
|
"jacked-star": drawJackedStar,
|
|
90
92
|
heart: drawHeart,
|
|
91
93
|
diamond: drawDiamond,
|
|
92
|
-
cube: drawCube
|
|
93
|
-
};
|
|
94
|
+
cube: drawCube,
|
|
95
|
+
};
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { defaultShapeConfig } from "../../constants";
|
|
2
2
|
import { applyTransforms, createCirclePoints, restoreContext } from "./utils";
|
|
3
3
|
|
|
4
|
+
interface PlatonicSolidConfig {
|
|
5
|
+
vertices: number;
|
|
6
|
+
faces: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface FibonacciConfig {
|
|
10
|
+
iterations: number;
|
|
11
|
+
growthFactor: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface GoldenRatioConfig {
|
|
15
|
+
iterations: number;
|
|
16
|
+
ratio: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
4
19
|
export const ShapeConfigs = {
|
|
5
20
|
platonic: {
|
|
6
21
|
tetrahedron: { vertices: 4, faces: 4 },
|
|
@@ -8,25 +23,43 @@ export const ShapeConfigs = {
|
|
|
8
23
|
octahedron: { vertices: 6, faces: 8 },
|
|
9
24
|
dodecahedron: { vertices: 20, faces: 12 },
|
|
10
25
|
icosahedron: { vertices: 12, faces: 20 },
|
|
11
|
-
},
|
|
26
|
+
} as Record<string, PlatonicSolidConfig>,
|
|
12
27
|
fibonacci: {
|
|
13
28
|
iterations: 13,
|
|
14
29
|
growthFactor: 1.618034, // Golden ratio
|
|
15
|
-
},
|
|
30
|
+
} as FibonacciConfig,
|
|
16
31
|
goldenRatio: {
|
|
17
32
|
iterations: 8,
|
|
18
33
|
ratio: 1.618034,
|
|
19
|
-
},
|
|
34
|
+
} as GoldenRatioConfig,
|
|
20
35
|
};
|
|
21
36
|
|
|
22
|
-
|
|
37
|
+
interface ShapeConfig {
|
|
38
|
+
fillStyle?: string;
|
|
39
|
+
strokeStyle?: string;
|
|
40
|
+
lineWidth?: number;
|
|
41
|
+
rotation?: number;
|
|
42
|
+
iterations?: number;
|
|
43
|
+
animate?: boolean;
|
|
44
|
+
type?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type DrawFunction = (
|
|
48
|
+
ctx: CanvasRenderingContext2D,
|
|
49
|
+
size: number,
|
|
50
|
+
config?: ShapeConfig,
|
|
51
|
+
) => void;
|
|
52
|
+
|
|
53
|
+
export const drawPlatonicSolid: DrawFunction = (ctx, size, config = {}) => {
|
|
23
54
|
const finalConfig = { ...defaultShapeConfig, ...config };
|
|
24
55
|
applyTransforms(ctx, size, finalConfig);
|
|
25
56
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
57
|
+
const solidType = config.type as keyof typeof ShapeConfigs.platonic;
|
|
58
|
+
const solidConfig = ShapeConfigs.platonic[solidType] ?? ShapeConfigs.platonic.icosahedron;
|
|
59
|
+
const {
|
|
60
|
+
vertices,
|
|
61
|
+
// faces
|
|
62
|
+
} = solidConfig;
|
|
30
63
|
const radius = size / 2;
|
|
31
64
|
|
|
32
65
|
// Calculate vertices based on platonic solid type
|
|
@@ -48,7 +81,7 @@ export const drawPlatonicSolid = (ctx, size, type, config = {}) => {
|
|
|
48
81
|
restoreContext(ctx);
|
|
49
82
|
};
|
|
50
83
|
|
|
51
|
-
export const drawFibonacciSpiral = (ctx, size, config = {}) => {
|
|
84
|
+
export const drawFibonacciSpiral: DrawFunction = (ctx, size, config = {}) => {
|
|
52
85
|
const finalConfig = {
|
|
53
86
|
...defaultShapeConfig,
|
|
54
87
|
...ShapeConfigs.fibonacci,
|
|
@@ -82,7 +115,7 @@ export const drawFibonacciSpiral = (ctx, size, config = {}) => {
|
|
|
82
115
|
restoreContext(ctx);
|
|
83
116
|
};
|
|
84
117
|
|
|
85
|
-
export const drawIslamicPattern = (ctx, size, config = {}) => {
|
|
118
|
+
export const drawIslamicPattern: DrawFunction = (ctx, size, config = {}) => {
|
|
86
119
|
const finalConfig = { ...defaultShapeConfig, ...config };
|
|
87
120
|
applyTransforms(ctx, size, finalConfig);
|
|
88
121
|
|
|
@@ -99,34 +132,29 @@ export const drawIslamicPattern = (ctx, size, config = {}) => {
|
|
|
99
132
|
// Draw star pattern at each intersection
|
|
100
133
|
const radius = unit / 2;
|
|
101
134
|
for (let k = 0; k < 8; k++) {
|
|
102
|
-
const angle = (
|
|
103
|
-
const x1 = x + Math.cos(angle)
|
|
104
|
-
const y1 = y + Math.sin(angle)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
135
|
+
const angle = (Math.PI / 4) * k;
|
|
136
|
+
const x1 = x + radius * Math.cos(angle);
|
|
137
|
+
const y1 = y + radius * Math.sin(angle);
|
|
138
|
+
const x2 = x + radius * Math.cos(angle + Math.PI / 4);
|
|
139
|
+
const y2 = y + radius * Math.sin(angle + Math.PI / 4);
|
|
140
|
+
ctx.moveTo(x1, y1);
|
|
141
|
+
ctx.lineTo(x2, y2);
|
|
110
142
|
}
|
|
111
|
-
ctx.closePath();
|
|
112
143
|
}
|
|
113
144
|
}
|
|
114
145
|
|
|
115
|
-
if (finalConfig.fillStyle !== "transparent") {
|
|
116
|
-
ctx.fill();
|
|
117
|
-
}
|
|
118
146
|
ctx.stroke();
|
|
119
147
|
restoreContext(ctx);
|
|
120
148
|
};
|
|
121
149
|
|
|
122
|
-
export const drawCelticKnot = (ctx, size, config = {}) => {
|
|
150
|
+
export const drawCelticKnot: DrawFunction = (ctx, size, config = {}) => {
|
|
123
151
|
const finalConfig = { ...defaultShapeConfig, ...config };
|
|
124
152
|
applyTransforms(ctx, size, finalConfig);
|
|
125
153
|
|
|
126
154
|
const gridSize = 4;
|
|
127
155
|
const unit = size / gridSize;
|
|
128
156
|
|
|
129
|
-
const drawKnotSegment = (x, y, type) => {
|
|
157
|
+
const drawKnotSegment = (x: number, y: number, type: string) => {
|
|
130
158
|
ctx.beginPath();
|
|
131
159
|
switch (type) {
|
|
132
160
|
case "over":
|
|
@@ -137,7 +165,7 @@ export const drawCelticKnot = (ctx, size, config = {}) => {
|
|
|
137
165
|
x + unit / 2,
|
|
138
166
|
y + unit,
|
|
139
167
|
x + unit,
|
|
140
|
-
y + unit
|
|
168
|
+
y + unit,
|
|
141
169
|
);
|
|
142
170
|
break;
|
|
143
171
|
case "under":
|
|
@@ -160,7 +188,7 @@ export const drawCelticKnot = (ctx, size, config = {}) => {
|
|
|
160
188
|
restoreContext(ctx);
|
|
161
189
|
};
|
|
162
190
|
|
|
163
|
-
export const drawMerkaba = (ctx, size, config = {}) => {
|
|
191
|
+
export const drawMerkaba: DrawFunction = (ctx, size, config = {}) => {
|
|
164
192
|
const finalConfig = { ...defaultShapeConfig, ...config };
|
|
165
193
|
applyTransforms(ctx, size, finalConfig);
|
|
166
194
|
|
|
@@ -194,12 +222,68 @@ export const drawMerkaba = (ctx, size, config = {}) => {
|
|
|
194
222
|
restoreContext(ctx);
|
|
195
223
|
};
|
|
196
224
|
|
|
197
|
-
export const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
225
|
+
export const drawMandala: DrawFunction = (ctx, size, config = {}) => {
|
|
226
|
+
const finalConfig = { ...defaultShapeConfig, ...config };
|
|
227
|
+
applyTransforms(ctx, size, finalConfig);
|
|
228
|
+
|
|
229
|
+
const numCircles = 8;
|
|
230
|
+
const numPoints = 16;
|
|
231
|
+
const radius = size / 2;
|
|
232
|
+
|
|
233
|
+
ctx.beginPath();
|
|
234
|
+
for (let i = 1; i <= numCircles; i++) {
|
|
235
|
+
const circleRadius = (radius / numCircles) * i;
|
|
236
|
+
ctx.moveTo(circleRadius, 0);
|
|
237
|
+
ctx.arc(0, 0, circleRadius, 0, Math.PI * 2);
|
|
238
|
+
|
|
239
|
+
for (let j = 0; j < numPoints; j++) {
|
|
240
|
+
const angle = (Math.PI * 2 * j) / numPoints;
|
|
241
|
+
const x = circleRadius * Math.cos(angle);
|
|
242
|
+
const y = circleRadius * Math.sin(angle);
|
|
243
|
+
ctx.moveTo(0, 0);
|
|
244
|
+
ctx.lineTo(x, y);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
ctx.stroke();
|
|
249
|
+
restoreContext(ctx);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export const drawFractal: DrawFunction = (ctx, size, config = {}) => {
|
|
253
|
+
const finalConfig = { ...defaultShapeConfig, ...config, iterations: 5 };
|
|
254
|
+
applyTransforms(ctx, size, finalConfig);
|
|
255
|
+
|
|
256
|
+
const drawBranch = (
|
|
257
|
+
x: number,
|
|
258
|
+
y: number,
|
|
259
|
+
length: number,
|
|
260
|
+
angle: number,
|
|
261
|
+
depth: number,
|
|
262
|
+
) => {
|
|
263
|
+
if (depth === 0) return;
|
|
264
|
+
|
|
265
|
+
const endX = x + length * Math.cos(angle);
|
|
266
|
+
const endY = y + length * Math.sin(angle);
|
|
267
|
+
|
|
268
|
+
ctx.beginPath();
|
|
269
|
+
ctx.moveTo(x, y);
|
|
270
|
+
ctx.lineTo(endX, endY);
|
|
271
|
+
ctx.stroke();
|
|
272
|
+
|
|
273
|
+
drawBranch(endX, endY, length * 0.7, angle - Math.PI / 6, depth - 1);
|
|
274
|
+
drawBranch(endX, endY, length * 0.7, angle + Math.PI / 6, depth - 1);
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
drawBranch(0, size / 2, size / 4, -Math.PI / 2, finalConfig.iterations);
|
|
278
|
+
restoreContext(ctx);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export const complexShapes: Record<string, DrawFunction> = {
|
|
282
|
+
platonicSolid: drawPlatonicSolid,
|
|
283
|
+
fibonacciSpiral: drawFibonacciSpiral,
|
|
284
|
+
islamicPattern: drawIslamicPattern,
|
|
285
|
+
celticKnot: drawCelticKnot,
|
|
286
|
+
merkaba: drawMerkaba,
|
|
287
|
+
mandala: drawMandala,
|
|
288
|
+
fractal: drawFractal,
|
|
205
289
|
};
|
|
@@ -2,7 +2,13 @@ import { basicShapes } from "./basic";
|
|
|
2
2
|
import { complexShapes } from "./complex";
|
|
3
3
|
import { sacredShapes } from "./sacred";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type DrawFunction = (
|
|
6
|
+
ctx: CanvasRenderingContext2D,
|
|
7
|
+
size: number,
|
|
8
|
+
config?: any,
|
|
9
|
+
) => void;
|
|
10
|
+
|
|
11
|
+
export const shapes: Record<string, DrawFunction> = {
|
|
6
12
|
...basicShapes,
|
|
7
13
|
...complexShapes,
|
|
8
14
|
...sacredShapes,
|