Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |
<meta name="theme-color" content="#000000" /> | |
<meta name="description" content="Web site created using create-react-app" /> | |
<link rel="preconnect" href="https://fonts.googleapis.com" /> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | |
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap" | |
rel="stylesheet" /> | |
<link | |
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&display=block" | |
rel="stylesheet" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/addons/p5.sound.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/gh/molleindustria/p5.play/lib/p5.play.js"></script> | |
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> | |
<title>Gemini Live API + p5.js</title> | |
</head> | |
<body> | |
<noscript>You need to enable JavaScript to run this app.</noscript> | |
<div id="root"></div> | |
<script> | |
let mySketch; | |
// Function to remove existing sketch instance | |
window.removeSketch = function() { | |
if (mySketch) { | |
if (mySketch._cleanup) { | |
mySketch._cleanup(); | |
} | |
mySketch.remove(); | |
mySketch = null; | |
} | |
}; | |
// Function to update the sketch with new code | |
window.updateSketch = function(sketchCode, container) { | |
console.log("Updating sketch with new code"); | |
try { | |
// Remove existing sketch if any | |
window.removeSketch(); | |
// Create new sketch instance | |
mySketch = new p5((p) => { | |
// Store container reference in p5 instance | |
p.containerWidth = container.clientWidth; | |
p.containerHeight = container.clientHeight; | |
let resizeTimeout = null; | |
let resizeObserver = null; | |
// Update container dimensions when needed | |
const updateContainerSize = () => { | |
const rect = container.getBoundingClientRect(); | |
const newWidth = rect.width; | |
const newHeight = rect.height; | |
// Only update if dimensions actually changed | |
if (p.containerWidth !== newWidth || p.containerHeight !== newHeight) { | |
p.containerWidth = newWidth; | |
p.containerHeight = newHeight; | |
if (p.windowResized) { | |
p.windowResized(); | |
} | |
} | |
}; | |
// Debounced resize handler | |
const debouncedResize = () => { | |
if (resizeTimeout) { | |
clearTimeout(resizeTimeout); | |
} | |
resizeTimeout = setTimeout(() => { | |
updateContainerSize(); | |
resizeTimeout = null; | |
}, 100); // Debounce for 100ms | |
}; | |
// Setup resize observer | |
const setupResizeObserver = () => { | |
if (resizeObserver) { | |
resizeObserver.disconnect(); | |
} | |
resizeObserver = new ResizeObserver((entries) => { | |
// Avoid processing if container is hidden or detached | |
if (container.offsetParent !== null) { | |
window.requestAnimationFrame(() => { | |
debouncedResize(); | |
}); | |
} | |
}); | |
resizeObserver.observe(container); | |
}; | |
// Add the sketch code to p5 instance scope | |
const sketchFunction = new Function('p', ` | |
with (p) { | |
${sketchCode} | |
// If setup/draw weren't defined, provide defaults | |
if (typeof setup !== 'function') { | |
setup = function() { | |
createCanvas(containerWidth, containerHeight); | |
} | |
} | |
if (typeof draw !== 'function') { | |
draw = function() { | |
background(0); | |
} | |
} | |
// Always ensure we have window resize handling | |
if (typeof windowResized !== 'function') { | |
windowResized = function() { | |
resizeCanvas(containerWidth, containerHeight, true); | |
} | |
} | |
return { setup, draw, windowResized }; | |
} | |
`); | |
// Get the sketch functions | |
const functions = sketchFunction(p); | |
// Assign the functions to p5 instance | |
p.setup = () => { | |
functions.setup.call(p); | |
// Ensure canvas is in container | |
if (container) { | |
container.innerHTML = ""; | |
container.appendChild(p._renderer.canvas); | |
// Fix accessibility tooltip issue | |
if (p._renderer.canvas) { | |
// Remove the default accessibility attributes that cause tooltips | |
p._renderer.canvas.removeAttribute('aria-label'); | |
p._renderer.canvas.removeAttribute('role'); | |
// Add a custom class to help with styling | |
p._renderer.canvas.classList.add('p5-managed-canvas'); | |
} | |
// Setup resize observer after canvas is added | |
setupResizeObserver(); | |
} | |
}; | |
p.draw = functions.draw.bind(p); | |
p.windowResized = functions.windowResized.bind(p); | |
// Cleanup when sketch is removed | |
p._cleanup = () => { | |
if (resizeObserver) { | |
resizeObserver.disconnect(); | |
resizeObserver = null; | |
} | |
if (resizeTimeout) { | |
clearTimeout(resizeTimeout); | |
resizeTimeout = null; | |
} | |
}; | |
}, container); | |
console.log("Successfully created new sketch"); | |
return true; | |
} catch (error) { | |
console.error("Error creating sketch:", error); | |
return false; | |
} | |
}; | |
window.initSketch = function (container) { | |
console.log("Initialize empty sketch"); | |
if (mySketch) { | |
return; | |
} | |
// Create initial empty sketch | |
window.updateSketch(` | |
function setup() { | |
createCanvas(containerWidth, containerHeight); | |
} | |
function draw() { | |
background(0); | |
} | |
`, container); | |
}; | |
</script> | |
</body> | |
</html> | |