@hypertools/sdk 0.3.2 → 0.4.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/README.md +175 -0
- package/dist/core/ExperienceController.d.ts +39 -0
- package/dist/core/ExperienceController.d.ts.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/index.js.map +3 -3
- package/dist/index.js +39 -39
- package/dist/index.js.map +3 -3
- package/examples/README.md +84 -0
- package/examples/p5js/index.html +39 -0
- package/examples/p5js/main.ts +136 -0
- package/examples/react/index.html +22 -0
- package/examples/react/main.tsx +310 -0
- package/examples/react-landing/README.md +64 -0
- package/examples/react-landing/index.html +14 -0
- package/examples/react-landing/package.json +23 -0
- package/examples/react-landing/public/boids-flocking-project.js +12 -0
- package/examples/react-landing/src/App.css +379 -0
- package/examples/react-landing/src/App.tsx +483 -0
- package/examples/react-landing/src/main.tsx +9 -0
- package/examples/react-landing/src/types.d.ts +24 -0
- package/examples/react-landing/tsconfig.json +20 -0
- package/examples/react-landing/vite.config.ts +9 -0
- package/examples/recording/index.html +113 -0
- package/examples/recording/main.ts +256 -0
- package/examples/threejs/index.html +40 -0
- package/examples/threejs/main.ts +196 -0
- package/examples/vanilla-canvas/index.html +77 -0
- package/examples/vanilla-canvas/main.ts +162 -0
- package/package.json +5 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vanilla Canvas Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates basic usage of @hypertools/sdk with the Canvas API.
|
|
5
|
+
* Creates an animated particle system with reactive parameters.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Experience } from '@hypertools/sdk';
|
|
9
|
+
|
|
10
|
+
interface Particle {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
vx: number;
|
|
14
|
+
vy: number;
|
|
15
|
+
radius: number;
|
|
16
|
+
life: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const experience = new Experience({
|
|
20
|
+
mount: document.getElementById('canvas-container')!,
|
|
21
|
+
paramDefs: {
|
|
22
|
+
color: { type: 'color', value: '#00ff88', label: 'Particle Color' },
|
|
23
|
+
speed: { type: 'number', value: 5, min: 1, max: 20, label: 'Speed' },
|
|
24
|
+
showTrails: { type: 'boolean', value: true, label: 'Show Trails' },
|
|
25
|
+
},
|
|
26
|
+
setup(context) {
|
|
27
|
+
// Create canvas
|
|
28
|
+
const canvas = document.createElement('canvas');
|
|
29
|
+
const ctx = canvas.getContext('2d')!;
|
|
30
|
+
canvas.width = 800;
|
|
31
|
+
canvas.height = 600;
|
|
32
|
+
context.mount.appendChild(canvas);
|
|
33
|
+
|
|
34
|
+
// Particle system state
|
|
35
|
+
const particles: Particle[] = [];
|
|
36
|
+
let mouseX = canvas.width / 2;
|
|
37
|
+
let mouseY = canvas.height / 2;
|
|
38
|
+
|
|
39
|
+
// Track mouse position
|
|
40
|
+
canvas.addEventListener('mousemove', (e) => {
|
|
41
|
+
const rect = canvas.getBoundingClientRect();
|
|
42
|
+
mouseX = e.clientX - rect.left;
|
|
43
|
+
mouseY = e.clientY - rect.top;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Spawn particles
|
|
47
|
+
function spawnParticle() {
|
|
48
|
+
const angle = Math.random() * Math.PI * 2;
|
|
49
|
+
const speed = context.params.speed as number;
|
|
50
|
+
|
|
51
|
+
particles.push({
|
|
52
|
+
x: mouseX,
|
|
53
|
+
y: mouseY,
|
|
54
|
+
vx: Math.cos(angle) * speed * (0.5 + Math.random()),
|
|
55
|
+
vy: Math.sin(angle) * speed * (0.5 + Math.random()),
|
|
56
|
+
radius: 3 + Math.random() * 5,
|
|
57
|
+
life: 1,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Draw frame
|
|
62
|
+
function draw() {
|
|
63
|
+
// Clear or fade based on trails setting
|
|
64
|
+
if (context.params.showTrails) {
|
|
65
|
+
ctx.fillStyle = 'rgba(26, 26, 46, 0.1)';
|
|
66
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
67
|
+
} else {
|
|
68
|
+
ctx.fillStyle = '#1a1a2e';
|
|
69
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Spawn new particles
|
|
73
|
+
for (let i = 0; i < 3; i++) {
|
|
74
|
+
spawnParticle();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Update and draw particles
|
|
78
|
+
const color = context.params.color as string;
|
|
79
|
+
|
|
80
|
+
for (let i = particles.length - 1; i >= 0; i--) {
|
|
81
|
+
const p = particles[i];
|
|
82
|
+
|
|
83
|
+
// Update position
|
|
84
|
+
p.x += p.vx;
|
|
85
|
+
p.y += p.vy;
|
|
86
|
+
p.life -= 0.01;
|
|
87
|
+
|
|
88
|
+
// Remove dead particles
|
|
89
|
+
if (p.life <= 0) {
|
|
90
|
+
particles.splice(i, 1);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Draw particle
|
|
95
|
+
ctx.beginPath();
|
|
96
|
+
ctx.arc(p.x, p.y, p.radius * p.life, 0, Math.PI * 2);
|
|
97
|
+
ctx.fillStyle = color + Math.floor(p.life * 255).toString(16).padStart(2, '0');
|
|
98
|
+
ctx.fill();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Draw particle count
|
|
102
|
+
ctx.fillStyle = '#fff';
|
|
103
|
+
ctx.font = '14px monospace';
|
|
104
|
+
ctx.fillText(`Particles: ${particles.length}`, 10, 20);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Listen to frame events
|
|
108
|
+
context.experience.on('frame', draw);
|
|
109
|
+
|
|
110
|
+
// Initial draw
|
|
111
|
+
draw();
|
|
112
|
+
|
|
113
|
+
// Cleanup
|
|
114
|
+
return () => {
|
|
115
|
+
canvas.remove();
|
|
116
|
+
particles.length = 0;
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Wire up UI controls
|
|
122
|
+
const toggleBtn = document.getElementById('toggle') as HTMLButtonElement;
|
|
123
|
+
const captureBtn = document.getElementById('capture') as HTMLButtonElement;
|
|
124
|
+
const colorInput = document.getElementById('color') as HTMLInputElement;
|
|
125
|
+
const speedInput = document.getElementById('speed') as HTMLInputElement;
|
|
126
|
+
const trailsInput = document.getElementById('showTrails') as HTMLInputElement;
|
|
127
|
+
|
|
128
|
+
toggleBtn.addEventListener('click', () => {
|
|
129
|
+
experience.toggle();
|
|
130
|
+
toggleBtn.textContent = experience.isPlaying ? 'Pause' : 'Play';
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
captureBtn.addEventListener('click', async () => {
|
|
134
|
+
const blob = await experience.captureImage('png');
|
|
135
|
+
if (blob) {
|
|
136
|
+
const url = URL.createObjectURL(blob);
|
|
137
|
+
const a = document.createElement('a');
|
|
138
|
+
a.href = url;
|
|
139
|
+
a.download = 'capture.png';
|
|
140
|
+
a.click();
|
|
141
|
+
URL.revokeObjectURL(url);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
colorInput.addEventListener('input', (e) => {
|
|
146
|
+
experience.setParam('color', (e.target as HTMLInputElement).value);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
speedInput.addEventListener('input', (e) => {
|
|
150
|
+
experience.setParam('speed', Number((e.target as HTMLInputElement).value));
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
trailsInput.addEventListener('change', (e) => {
|
|
154
|
+
experience.setParam('showTrails', (e.target as HTMLInputElement).checked);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Sync initial values
|
|
158
|
+
experience.on('ready', () => {
|
|
159
|
+
colorInput.value = experience.params.color as string;
|
|
160
|
+
speedInput.value = String(experience.params.speed);
|
|
161
|
+
trailsInput.checked = experience.params.showTrails as boolean;
|
|
162
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypertools/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Vanilla-first SDK for embedding interactive creative coding experiences. Supports p5.js, Three.js, WebGL, and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"dist/recording",
|
|
44
44
|
"dist/react",
|
|
45
45
|
"dist/capture",
|
|
46
|
+
"examples",
|
|
46
47
|
"README.md",
|
|
47
48
|
"LICENSE"
|
|
48
49
|
],
|
|
@@ -158,5 +159,8 @@
|
|
|
158
159
|
"react": "^18.3.1",
|
|
159
160
|
"react-dom": "^18.3.1",
|
|
160
161
|
"typescript": "^5.6.2"
|
|
162
|
+
},
|
|
163
|
+
"dependencies": {
|
|
164
|
+
"@hypertools/sdk": "0.3.3"
|
|
161
165
|
}
|
|
162
166
|
}
|