🔍 About This Code Showcase
This curated code demonstration showcases how the AI Coloring Book creates educational experiences by combining AI-generated content with interactive canvas technology designed specifically for children.
Full deployment configurations, API keys, and proprietary details are omitted for security. This showcase highlights the core educational canvas engine and child-centered AI integration algorithms.
🎨 Core Algorithm: Interactive Canvas Engine
The heart of the AI Coloring Book is its sophisticated canvas system that combines flood-fill algorithms with child-friendly interactions, optimized for educational development and motor skill enhancement:
import React, { useRef, useEffect, useCallback, forwardRef, useImperativeHandle } from 'react';
interface ColoringCanvasProps {
imageUrl: string;
color: string;
onHistoryChange: (canUndo: boolean) => void;
}
export interface CanvasHandle {
undo: () => void;
}
export const ColoringCanvas = forwardRef(
({ imageUrl, color, onHistoryChange }, ref) => {
const canvasRef = useRef(null);
const imageRef = useRefnull>(null);
const historyRef = useRef([]);
const hexToRgb = (hex: string) => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
};
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const context = canvas.getContext('2d', { willReadFrequently: true });
if (!context) return;
const img = new Image();
img.crossOrigin = "anonymous";
img.src = imageUrl;
img.onload = () => {
const parent = canvas.parentElement;
if (parent) {
const size = Math.min(parent.clientWidth, parent.clientHeight);
canvas.width = size;
canvas.height = size;
context.drawImage(img, 0, 0, canvas.width, canvas.height);
imageRef.current = img;
const initialImageData = context.getImageData(0, 0, canvas.width, canvas.height);
historyRef.current = [initialImageData];
onHistoryChange(false);
}
};
}, [imageUrl, onHistoryChange]);
const floodFill = useCallback((
ctx: CanvasRenderingContext2D,
startX: number,
startY: number,
fillColor: {r: number, g: number, b: number}
) => {
const canvas = ctx.canvas;
const { width, height } = canvas;
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
const startPos = (startY * width + startX) * 4;
const startR = data[startPos];
const startG = data[startPos + 1];
const startB = data[startPos + 2];
if (startR === fillColor.r && startG === fillColor.g && startB === fillColor.b) {
return;
}
const isLine = (r: number, g: number, b: number) => r < 50 && g < 50 && b < 50;
if (isLine(startR, startG, startB)) {
return;
}
const tolerance = 30;
const colorMatch = (pos: number) => {
const r = data[pos];
const g = data[pos + 1];
const b = data[pos + 2];
return Math.abs(r - startR) <= tolerance &&
Math.abs(g - startG) <= tolerance &&
Math.abs(b - startB) <= tolerance;
};
const pixelStack = [[startX, startY]];
while (pixelStack.length) {
const newPos = pixelStack.pop();
if (!newPos) continue;
let [x, y] = newPos;
let currentPos = (y * width + x) * 4;
while (y-- >= 0 && colorMatch(currentPos)) {
currentPos -= width * 4;
}
currentPos += width * 4;
++y;
let reachLeft = false;
let reachRight = false;
while (y++ < height - 1 && colorMatch(currentPos)) {
data[currentPos] = fillColor.r;
data[currentPos + 1] = fillColor.g;
data[currentPos + 2] = fillColor.b;
data[currentPos + 3] = 255;
if (x > 0) {
if (colorMatch(currentPos - 4)) {
if (!reachLeft) {
pixelStack.push([x - 1, y]);
reachLeft = true;
}
} else if (reachLeft) {
reachLeft = false;
}
}
if (x < width - 1) {
if (colorMatch(currentPos + 4)) {
if (!reachRight) {
pixelStack.push([x + 1, y]);
reachRight = true;
}
} else if (reachRight) {
reachRight = false;
}
}
currentPos += width * 4;
}
}
ctx.putImageData(imageData, 0, 0);
}, []);
🤖 AI Generation Engine: Child-Safe Content Creation
The AI generation system creates educational, age-appropriate coloring pages using Google Gemini's image generation with specialized prompts designed for child development:
import { GoogleGenAI } from "@google/genai";
const API_KEY = process.env.API_KEY;
if (!API_KEY) {
throw new Error("API_KEY environment variable not set");
}
const ai = new GoogleGenAI({ apiKey: API_KEY });
export const generateColoringPage = async (theme: string): Promise => {
const prompt = `A simple, black and white coloring book page for a toddler.
The theme is "${theme}".
The image must have:
- Clear, thick, solid black outlines
- Large, easy-to-color areas perfect for developing motor skills
- No shading, no grayscale, no complex details
- Clean white background for optimal contrast
- Age-appropriate, educational content that encourages learning`;
try {
const response = await ai.models.generateImages({
model: 'imagen-4.0-generate-001',
prompt: prompt,
config: {
numberOfImages: 1,
outputMimeType: 'image/png',
aspectRatio: '1:1',
},
});
if (response.generatedImages && response.generatedImages.length > 0) {
const base64ImageBytes: string = response.generatedImages[0].image.imageBytes;
return base64ImageBytes;
} else {
throw new Error("No image was generated by the API.");
}
} catch (error) {
console.error("Error generating image with Gemini AI:", error);
throw new Error("Oops! We couldn't create a picture. Please try another theme.");
}
};
🎮 Interactive Controls & User Experience
The application state management combines React's modern patterns with child-centered design principles for an intuitive, educational experience:
import React, { useState, useCallback, useRef }
from 'react';
import { ColorPalette }
from './components/ColorPalette';
import { ColoringCanvas, CanvasHandle }
from './components/ColoringCanvas';
import { ThemeControls }
from './components/ThemeControls';
import { generateColoringPage }
from './services/geminiService';
const App: React.FC = () => {
const [theme, setTheme] = useState
('');
const [activePrompt, setActivePrompt] = useState('');
const [imageUrl, setImageUrl] = useStatenull>(null);
const [selectedColor, setSelectedColor] = useState(COLORS[0]);
const [isLoading, setIsLoading] = useState(false);
const [canUndo, setCanUndo] = useState(false);
const canvasRef = useRef(null);
const handleGenerate = useCallback(async (currentTheme: string) => {
if (!currentTheme || isLoading) return;
setIsLoading(true);
setError(null);
setImageUrl(null);
setCanUndo(false);
try {
const generatedImage = await generateColoringPage(currentTheme);
setImageUrl(`data:image/png;base64,${generatedImage}`);
setActivePrompt(currentTheme);
setCanvasKey(Date.now());
} catch (err) {
console.error(err);
setError('Oops! We couldn\'t create a picture. Please try another theme.');
} finally {
setIsLoading(false);
}
}, [isLoading]);
const handleNext = useCallback(() => {
if (activePrompt) {
setCanUndo(false);
handleGenerate(activePrompt);
}
}, [activePrompt, handleGenerate]);
const handleRefresh = useCallback(() => {
setCanvasKey(Date.now());
setCanUndo(false);
}, []);
const handleUndo = useCallback(() => {
canvasRef.current?.undo();
}, []);
return (
"min-h-screen flex flex-col items-center justify-center p-4">
);
};
🎨 Educational Color Palette System
The color palette is carefully designed with child development principles, featuring 12 colors selected for their educational value and psychological impact on young learners:
export const COLORS = [
'#FF5252',
'#FF7900',
'#FFD000',
'#4CAF50',
'#3498DB',
'#9B59B6',
'#E91E63',
'#964B00',
'#212121',
'#9E9E9E',
'#FFFFFF',
'#00BCD4'
];
export const COLOR_CATEGORIES = {
primary: ['#FF5252', '#FFD000', '#3498DB'],
secondary: ['#FF7900', '#4CAF50', '#9B59B6'],
neutral: ['#212121', '#9E9E9E', '#FFFFFF'],
expressive: ['#E91E63', '#964B00', '#00BCD4']
};