Advanced Dynamic NFT Techniques
This guide covers advanced techniques for creating more complex and performant Dynamic NFTs.
Responsive Canvas
When working with P5.js, you might want your artwork to be responsive to different window sizes:
let scale = 1;
function setup() {
// Create a responsive canvas
createCanvas(windowWidth, windowHeight);
// Calculate scale based on minimum dimension
scale = min(width, height) / 1024;
// Scale all subsequent drawing operations
scale(scale);
}
function windowResized() {
// Update canvas and scale when window is resized
resizeCanvas(windowWidth, windowHeight);
scale = min(width, height) / 1024;
redraw(); // Trigger redraw with new dimensions
}
Always test your artwork at different screen sizes to ensure a consistent experience.
Progressive Rendering with Generators
For complex artworks that might cause browser lag, you can use JavaScript generators to break down the rendering process:
function* generateArtwork() {
// Initial setup
background(220);
// Generate parameters
const particles = Array(1000)
.fill()
.map(() => ({
x: genify.random() * width,
y: genify.random() * height,
size: genify.randFloat(2, 10),
}));
// Render in batches
for (let i = 0; i < particles.length; i += 10) {
const batch = particles.slice(i, i + 10);
batch.forEach((p) => {
circle(p.x, p.y, p.size);
});
// Yield after each batch to prevent browser freeze
yield i / particles.length; // Return progress (0-1)
}
}
let generator;
let isRendering = false;
function setup() {
createCanvas(1024, 1024);
noLoop();
// Create loading UI
loadingText = createDiv("Rendering: 0%");
loadingText.position(10, 10);
// Start rendering
startRendering();
}
async function startRendering() {
if (isRendering) return;
isRendering = true;
generator = generateArtwork();
while (true) {
const result = generator.next();
if (result.done) {
loadingText.html("Rendering Complete!");
genify.renderDone();
break;
}
// Update loading progress
loadingText.html(`Rendering: ${(result.value * 100).toFixed(1)}%`);
// Allow browser to update UI
await new Promise((resolve) => setTimeout(resolve, 0));
}
isRendering = false;
}
For more complex examples and in-depth understanding of generators in creative coding, check out this excellent guide on using generators for animated sketches (opens in a new tab).
Memory Management
When creating complex artworks, it's important to manage memory efficiently:
function draw() {
// Clear any existing objects
cleanup();
// Create new objects
const particles = createParticles();
// Render in batches
renderBatches(particles);
// Clean up after rendering
cleanup();
}
function cleanup() {
// Remove any existing DOM elements
while (document.getElementsByClassName("temp").length > 0) {
document.getElementsByClassName("temp")[0].remove();
}
// Clear graphics buffers
if (buffer) {
buffer.remove();
buffer = null;
}
}
Using Off-screen Buffers
For complex effects, use P5.js graphics buffers to render off-screen:
let buffer;
function setup() {
createCanvas(1024, 1024);
// Create off-screen buffer
buffer = createGraphics(1024, 1024);
}
function draw() {
// Render complex effects to buffer
buffer.push();
buffer.translate(width / 2, height / 2);
// ... complex rendering ...
buffer.pop();
// Draw buffer to main canvas
image(buffer, 0, 0);
}
Performance Tips
-
Batch Processing
- Group similar operations together
- Process in small chunks using generators
- Use requestAnimationFrame for smooth animations
-
Memory Management
- Clean up unused objects and buffers
- Reuse objects instead of creating new ones
- Use object pools for particle systems
-
Rendering Optimization
- Use off-screen buffers for complex effects
- Implement level of detail based on performance
- Cache repeated calculations
Error Handling
Always implement error handling to ensure your artwork degrades gracefully:
try {
// Attempt complex rendering
await startRendering();
} catch (error) {
console.error("Rendering failed:", error);
// Fallback to simple rendering
renderFallback();
genify.renderDone();
}
Next Steps
- Experiment with different generator patterns
- Implement complex particle systems
- Try combining multiple rendering techniques
- Study the P5.js performance documentation (opens in a new tab)