xxxxxxxxxx
// **SETTINGS**
const animationTypes = {
circle: "circle",
swirl: "swirl",
};
const animationType = "swirl";
const maxSpeed = 0.4;
const minSpeed = 0.1;
let timeStep = 0.01;
const myFrameRate = 60;
const screenWidth = 1280;
const screenHeight = 720;
const screenRatio = screenWidth / screenHeight;
const gridSize = 16;
const bgColor = [255, 255, 255];
const textColor = [240, 240, 240];
const words = [
"Ìwò̩fà", "ń", "yò̩", "séji", "tó", "gbojúmó̩,", "ó", "hàn", "pákànpò̩", "gan-an", "nis̩é̩", "rè̩", "bó", "dò̩la", // Yoruba
"Parciais", "fy", "jac", "codi", "baw", "hud", "llawn", "dŵr", "ger", "tŷ", "Mabon", // Welsh
"Nafurahi", "kukuona", // Swahili
"إِنَا", "سُونْ", "زُوَا", "كَاسُوَا", "يَاوُ", "دَا", "سَافِي", // Hausa
"Murakaza", "neza", "Hashize", "iminsi", "tutabonana" // kinyarwanda
];
const debugMode = false;
// ************
let sentences = [];
let chars = [];
let maxSentenceCount;
let maxSentenceLength;
function generateSentence() {
// Generate a random sentence by selecting random words from the words array
let sentence = "- ";
let numWords = Math.floor(Math.random() * 20) + 5;
for (let i = 0; i < numWords; i++) {
let wordIndex = Math.floor(Math.random() * words.length);
sentence += words[wordIndex] + " ";
}
return sentence;
}
function setup() {
createCanvas(windowWidth, windowHeight);
frameRate(myFrameRate);
textFont("Courier New");
textSize(gridSize);
noStroke();
fill(255);
// Adjust maxSentenceCount and maxSentenceLength based on the dynamic window size
maxSentenceCount = int(windowHeight / gridSize);
maxSentenceLength = int(windowWidth / gridSize);
// generate the sentences to be displayed
let sentencesCountSoFar = sentences.length;
for (let i = 0; i < maxSentenceCount - sentencesCountSoFar; i++) {
sentences.push(generateSentence());
}
// cap sentence length
for (let y = 0; y < sentences.length; y++) {
let sentence = sentences[y];
sentence = sentence.slice(0, maxSentenceLength);
sentences[y] = sentence;
}
// fill grid with sentences
for (let y = 0; y < maxSentenceCount; y++) {
let row = [];
for (let x = 0; x < maxSentenceLength; x++) {
row.push({
character: sentences[y][x] || " ",
x: x,
y: y,
});
}
chars.push(row);
}
if (debugMode) {
chars[5][15].character = ":";
console.log("In debug mode. Click the canvas for next frame.");
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
// Re-calculate any layout or size-dependent variables here
maxSentenceCount = int(windowHeight / gridSize);
maxSentenceLength = int(windowWidth / gridSize);
// You may also need to regenerate or adjust content based on the new size
}
function drawCheckerboard(size, rows, cols) {
// for debugging, or aesthetics
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
if ((x + y) % 2 == 0) {
fill(20); // White
} else {
fill(bgColor); // Black
}
rect(x * size, y * size, size, size);
}
}
}
function draw() {
background(bgColor);
fill(textColor);
textSize(gridSize);
noStroke();
textLeading(gridSize);
if (debugMode) {
drawCheckerboard(gridSize, maxSentenceCount, maxSentenceLength);
}
// Create a new array to store the characters that should be displayed at each grid position
let displayChars = [];
for (let y = 0; y < maxSentenceCount; y++) {
let row = [];
for (let x = 0; x < maxSentenceLength; x++) {
row.push(" ");
}
displayChars.push(row);
}
// Calculate the center of the screen
let centerX = maxSentenceLength / 2;
let centerY = maxSentenceCount / 2;
let radius = min(maxSentenceLength, maxSentenceCount) / 2;
// Animate the characters
// timeStep += 0.001
for (let y = 0; y < chars.length; y++) {
let sentence = chars[y];
for (let x = 0; x < sentence.length; x++) {
let character = sentence[x];
// Calculate the new x and y positions of the character
let distanceX = character.x - centerX;
let distanceY = character.y - centerY;
let distance = sqrt(distanceX * distanceX + distanceY * distanceY);
let angle = atan2(distanceY, distanceX);
let newX, newY;
// update the character's position based on the desired animation type
if (animationType === animationTypes.circle) {
// new pos for circling
newX = centerX + cos(angle + timeStep) * distance;
newY = centerY + sin(angle + timeStep) * distance;
} else if (animationType === animationTypes.swirl) {
// new pos for swirling
// Calculate the speed factor based on the distance from the center
let speedFactor = map(
distance,
0,
max(maxSentenceLength, maxSentenceCount) / 2,
maxSpeed,
minSpeed
);
// rotate in an ellipse instead of a circle
let stretchX = 1;
let stretchY = 1;
if (screenRatio > 1) {
// Screen is wider than it is tall
stretchX = screenRatio;
} else if (screenRatio < 1) {
// Screen is taller than it is wide
stretchY = 1 / screenRatio;
}
newX = centerX + cos(angle - timeStep * speedFactor * stretchX) * distance;
newY = centerY + sin(angle - timeStep * speedFactor * stretchY) * distance;
} else {
throw new Error("No valid animation type chosen");
}
// update the character's floating point coords
character.x = newX;
character.y = newY;
// put the character in a spot on the displayChars grid
if (
round(newY) >= 0 &&
round(newY) < maxSentenceCount &&
round(newX) >= 0 &&
round(newX) < maxSentenceLength
) {
displayChars[round(newY)][round(newX)] = character.character;
}
if (debugMode) {
if (character.character == ":") {
console.log(
`dist ${distance} | angle ${angle} | cos ${cos(
angle + timeStep
)} | moved (${x}, ${y}) to (${newX}, ${newY})`
);
}
}
}
}
// draw the characters in the displayChars grid
for (let y = 0; y < displayChars.length; y++) {
let sentence = displayChars[y];
for (let x = 0; x < sentence.length; x++) {
if (debugMode) {
if (sentence[x] == ":") {
fill(100, 0, 0);
noStroke();
rect(x * gridSize, y * gridSize, gridSize, gridSize);
}
}
let character = sentence[x];
textSize(gridSize);
noStroke();
fill(textColor);
text(character, x * gridSize, (y + 1) * gridSize);
}
}
if (debugMode) {
noLoop();
}
}
function mousePressed() {
// When the mouse is clicked, call loop() to start the sketch again
if (debugMode) {
loop();
} else {
// Call the changeColor function defined in the global scope
if (typeof window.changeColor === 'function') {
window.changeColor();
}
}
}
document.addEventListener('colorChange', function(e) {
// Update bgColor and textColor with the values from the event
bgColor = e.detail.bgColor;
textColor = e.detail.textColor;
// Optionally, redraw the canvas to immediately see the color change
redraw(); // Make sure this is called if not in a draw loop
});