help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
star-pattern-maker
/
js
RSK World
star-pattern-maker
Star Pattern Maker - HTML5 Canvas + 3D Rendering + Physics Simulation + AI Patterns + Generative Audio + Modern UI + Glassmorphism Design
js
  • 3d-engine.js3.8 KB
  • ai-patterns.js5.6 KB
  • animations.js1.4 KB
  • audio.js1.3 KB
  • controls.js12.2 KB
  • export.js3.9 KB
  • filters.js3.5 KB
  • fractals.js3.5 KB
  • gallery.js2.5 KB
  • main.js1.9 KB
  • particles.js1.4 KB
  • physics.js1.7 KB
  • presets.js2.8 KB
  • randomizer.js1.4 KB
  • renderer.js7 KB
  • shaders.js6.5 KB
  • shapes.js1.7 KB
  • sound-gen.js4.4 KB
  • state.js1.9 KB
  • symmetry.js3.9 KB
  • themes.js1.4 KB
  • timeline.js4.2 KB
  • utils.js546 B
audio.jsgallery.jsfractals.jsshapes.js
js/audio.js
Raw Download
Find: Go to:
/* V7 Audio Module */
import { state } from './state.js';

let audioContext = null;
let analyser = null;
let dataArray = null;

export function initAudio() {
    if (audioContext) return;

    try {
        audioContext = new (window.AudioContext || window.webkitAudioContext)();
        analyser = audioContext.createAnalyser();
        analyser.fftSize = 64;

        navigator.mediaDevices.getUserMedia({ audio: true })
            .then(stream => {
                const source = audioContext.createMediaStreamSource(stream);
                source.connect(analyser);
                dataArray = new Uint8Array(analyser.frequencyBinCount);
            })
            .catch(err => {
                console.error("Audio Access Denied", err);
                alert("Microphone access denied. Visualizer disabled.");
                state.audioMode = false;
                // Dispatch event to uncheck box? handled by loop checking state
            });
    } catch (e) {
        console.error(e);
    }
}

export function getAudioData() {
    if (!audioContext || !analyser || !state.audioMode) return null;

    analyser.getByteFrequencyData(dataArray);

    const avg = dataArray.reduce((p, c) => p + c, 0) / dataArray.length;
    const bass = dataArray[2];

    return { avg, bass };
}
43 lines•1.3 KB
javascript
js/gallery.js
Raw Download
Find: Go to:
/* V7 Gallery Module */
import { state } from './state.js';

const STORAGE_KEY = 'star_patterns_gallery';

export function savePattern(name, thumbDataUrl) {
    const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
    const pattern = {
        id: Date.now(),
        name: name || 'Untitled Pattern',
        date: new Date().toLocaleDateString(),
        thumbnail: thumbDataUrl,
        state: { ...state } // Clone state
    };
    saved.unshift(pattern); // Add to top
    localStorage.setItem(STORAGE_KEY, JSON.stringify(saved));
    renderGallery();
}

export function loadPattern(id) {
    const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
    const pattern = saved.find(p => p.id === id);
    if (pattern) {
        // Restore State
        Object.keys(pattern.state).forEach(k => {
            state[k] = pattern.state[k];
        });
        return true;
    }
    return false;
}

export function deletePattern(id) {
    let saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
    saved = saved.filter(p => p.id !== id);
    localStorage.setItem(STORAGE_KEY, JSON.stringify(saved));
    renderGallery();
}

export function renderGallery() {
    const container = document.getElementById('galleryContainer');
    if (!container) return; // Should exist in HTML

    const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');

    if (saved.length === 0) {
        container.innerHTML = '<p style="color:var(--text-secondary); text-align:center;">No saved patterns</p>';
        return;
    }

    container.innerHTML = '';
    saved.forEach(p => {
        const item = document.createElement('div');
        item.className = 'gallery-item';
        item.innerHTML = `
            <img src="${p.thumbnail}" alt="${p.name}">
            <div class="info">
                <span>${p.name}</span>
                <button class="btn-sm delete-btn" data-id="${p.id}">&times;</button>
            </div>
        `;

        // Load click
        item.querySelector('img').addEventListener('click', () => {
            const event = new CustomEvent('loadPattern', { detail: p.id });
            window.dispatchEvent(event);
        });

        // Delete click
        item.querySelector('.delete-btn').addEventListener('click', (e) => {
            e.stopPropagation();
            if (confirm('Delete this pattern?')) deletePattern(p.id);
        });

        container.appendChild(item);
    });
}
78 lines•2.5 KB
javascript
js/fractals.js
Raw Download
Find: Go to:
/* V9 Fractal Logic */
import { state } from './state.js';
import { drawStarPath } from './shapes.js';
import { getJitter } from './utils.js';

export function drawFractalStar(ctx, rOuter, rInner, depth) {
    if (depth <= 0) return;

    // Draw Main Star at current level
    drawStarPath(ctx, state.spikes, rOuter, rInner, state.curve, state.twist);

    // We only stroke/fill at the leaf level or complex composite?
    // Let's just draw paths. The caller fills/strokes.
    // Actually, to make it visible, we need to recurse at the TIPS (outer points).

    // Calculate tip positions
    const spikes = state.spikes;
    const step = Math.PI / spikes;
    let rot = Math.PI / 2 * 3;

    // We need to iterate coordinates manually here to translate to them
    // This replicates shapes.js logic but just for finding points

    for (let i = 0; i < spikes; i++) {
        // Outer Point (Tip)
        let outerRot = rot + step;
        // Note: shapes.js logic is slightly offset. 
        // Let's rely on standard geometry:
        // Angle = rot

        // Wait, drawStarPath handles the path. 
        // To draw recursive stars, we need to Translate to the tip, Transform, and Draw again.

        let cx = Math.cos(outerRot + step) * rOuter; // shapes.js loop is weird.
        // Let's simplify: Standard Polars.
        // Tip angles are: -PI/2 + (i * 2PI/spikes)

        const angle = -Math.PI / 2 + (i * (Math.PI * 2) / spikes);
        const x = Math.cos(angle) * rOuter;
        const y = Math.sin(angle) * rOuter;

        ctx.save();
        ctx.translate(x, y);
        ctx.scale(0.4, 0.4); // Scale down
        ctx.rotate(angle + Math.PI / 2); // Align?

        // Recurse
        drawFractalStar(ctx, rOuter, rInner, depth - 1);

        ctx.restore();
    }
}

// Alternative: A dedicated recursive render function that handles Fill/Stroke per level?
// It's cleaner to just generate one complex path? 
// No, separate stars look better for snowflakes.

export function renderRecursiveFractal(ctx, w, h, rOuter, rInner) {
    const depth = state.fractalDepth || 0;

    // Helper recursive function
    function recurse(d, rO, rI) {
        if (d <= 0) return;

        // Draw current star
        ctx.beginPath();
        drawStarPath(ctx, state.spikes, rO, rI, state.curve, state.twist);
        ctx.fill();
        if (state.lineWidth > 0) ctx.stroke();

        // If we want recursion at tips
        const angleStep = (Math.PI * 2) / state.spikes;

        for (let i = 0; i < state.spikes; i++) {
            const angle = -Math.PI / 2 + (i * angleStep);
            // The tip position
            const startAngle = (Math.PI / 2 * 3); // shapes.js start
            // shapes.js logic is: outer point is at `rot + step`
            // i=0: outerRot = start + PI/spikes. 

            // Let's calculate tip x,y based on shapes.js logic to be consistent
            let rot = startAngle + (i * angleStep);
            let outerRot = rot + (Math.PI / state.spikes);

            let tipX = Math.cos(outerRot) * rO;
            let tipY = Math.sin(outerRot) * rO;

            ctx.save();
            ctx.translate(tipX, tipY);
            ctx.scale(0.4, 0.4);
            ctx.rotate(outerRot + Math.PI / 2); // Align with spoke

            recurse(d - 1, rO, rI);

            ctx.restore();
        }
    }

    // Start recursion
    // We need loop for main star? No, recurse handles it.
    // Center logic handled by renderer.js transform.
    recurse(depth, rOuter, rInner);
}
104 lines•3.5 KB
javascript
js/shapes.js
Raw Download
Find: Go to:
/* V7 Shape Logic */
import { getJitter } from './utils.js';

export function drawStarPath(ctx, spikes, outerRadius, innerRadius, curveVal, twistVal) {
    let rot = Math.PI / 2 * 3;
    const step = Math.PI / spikes;
    const twistRad = (twistVal * Math.PI) / 180;

    ctx.beginPath();
    ctx.moveTo(0 + getJitter(), -outerRadius + getJitter());

    for (let i = 0; i < spikes; i++) {
        let twistedInnerRot = rot + step + twistRad;
        let innerX = Math.cos(twistedInnerRot) * innerRadius + getJitter();
        let innerY = Math.sin(twistedInnerRot) * innerRadius + getJitter();

        if (curveVal === 0) {
            ctx.lineTo(innerX, innerY);
        } else {
            let cpAngle = (rot + twistedInnerRot) / 2;
            let cpR = (outerRadius + innerRadius) / 2 + curveVal;
            let cpX = Math.cos(cpAngle) * cpR + getJitter();
            let cpY = Math.sin(cpAngle) * cpR + getJitter();
            ctx.quadraticCurveTo(cpX, cpY, innerX, innerY);
        }

        rot += step;

        let outerRot = rot + step;
        let outerX = Math.cos(outerRot) * outerRadius + getJitter();
        let outerY = Math.sin(outerRot) * outerRadius + getJitter();

        if (curveVal === 0) {
            ctx.lineTo(outerX, outerY);
        } else {
            let cpAngle = (rot + twistRad + outerRot) / 2;
            let cpR = (outerRadius + innerRadius) / 2 + curveVal;
            let cpX = Math.cos(cpAngle) * cpR + getJitter();
            let cpY = Math.sin(cpAngle) * cpR + getJitter();
            ctx.quadraticCurveTo(cpX, cpY, outerX, outerY);
        }

        rot += step;
    }

    ctx.closePath();
}
48 lines•1.7 KB
javascript
🚀 Support RSK World

Subscribe to our YouTube channel for latest tutorials & updates!



Click subscribe & support our work ❤️

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer