// 002 - Phyllotaxis Spiral (organic)
// 1:1 Original algorithm engine source
function createPhyllotaxisSpiral() {
return {
setup() {
},
render(context, timeState, params) {
const { ctx, width, height } = context;
const count = Number(params.pointCount || 1200);
const c = Number(params.scaleFactor || 6);
const speed = Number(params.rotationSpeed || 0.5);
const divergence = Number(params.divergenceAngle || 137.508) * (Math.PI / 180);
ctx.fillStyle = "#08090d";
ctx.fillRect(0, 0, width, height);
const cx = width * 0.5;
const cy = height * 0.5;
const t = timeState.time * speed;
for (let n = 0; n < count; n++) {
const theta = n * divergence + t * (1 + n * 2e-4);
const r = c * Math.sqrt(n) * (1 + 0.05 * Math.sin(t * 2 + n * 0.02));
const x = cx + r * Math.cos(theta);
const y = cy + r * Math.sin(theta);
if (x < -20 || x > width + 20 || y < -20 || y > height + 20) continue;
const size = Math.max(1, r / (width * 0.5) * 4 + 1.2);
const hue = (n * 0.35 + t * 40) % 360;
ctx.fillStyle = hsla(hue, 90, 65, 0.85);
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fill();
}
}
};
}
// Default parameters from content metadata
const defaultParams = [
{
"key": "divergenceAngle",
"label": "Divergence Angle (°)",
"type": "range",
"min": 137,
"max": 138,
"step": 0.001,
"defaultValue": 137.508,
"description": "Golden ratio packing angle"
},
{
"key": "scaleFactor",
"label": "Scale Factor (c)",
"type": "range",
"min": 2,
"max": 12,
"step": 0.2,
"defaultValue": 6,
"description": "Radial distribution density"
},
{
"key": "rotationSpeed",
"label": "Rotation Speed",
"type": "range",
"min": 0.1,
"max": 2,
"step": 0.05,
"defaultValue": 0.5,
"description": "Temporal rotation multiplier"
},
{
"key": "pointCount",
"label": "Seed Count",
"type": "range",
"min": 300,
"max": 2400,
"step": 50,
"defaultValue": 1200,
"description": "Total seed floret points"
}
];
if (!window.__art_instances) window.__art_instances = {};
if (!window.__art_instances['phyllotaxis-spiral']) {
const inst = typeof createPhyllotaxisSpiral === 'function' ? createPhyllotaxisSpiral() : null;
if (inst && inst.setup) {
inst.setup({ ctx, width, height, dpr: 1, aspectRatio: width / height }, defaultParams);
}
window.__art_instances['phyllotaxis-spiral'] = inst;
}
const instance = window.__art_instances['phyllotaxis-spiral'];
if (instance && instance.render) {
instance.render(
{ ctx, width, height, dpr: 1, aspectRatio: width / height },
{ time, deltaTime: dt, frameCount: Math.floor(time * 60), fps: 60 },
defaultParams
);
}