“rtexttt_2” by wy
https://openprocessing.org/sketch/2509160
License CreativeCommons Attribution NonCommercial ShareAlike
https://creativecommons.org/licenses/by-nc-sa/3.0
{{filePath}}
{{width}} x {{height}}
Report Sketch
Oh, that naughty sketch! Please let us know what the issue is below.
Apply Template
Applying this template will reset your sketch and remove all your changes. Are you sure you would like to continue?
Report Sketch
Report Comment
Please confirm that you would like to report the comment below.
We will review your submission and take any actions necessary per our Community Guidelines. In addition to reporting this comment, you can also block the user to prevent any future interactions.
Please report comments only when necessary. Unnecessary or abusive use of this tool may result in your own account being suspended.
Are you sure you want to delete your sketch?
Any files uploaded will be deleted as well.
Delete Comment?
This will also delete all the replies to this comment.
Delete this tab? Any code in it will be deleted as well.
Select a collection to submit your sketch
We Need Your Support
Since 2008, OpenProcessing has provided tools for creative coders to learn, create, and share over a million open source projects in a friendly environment.
Niche websites like ours need your continued support for future development and maintenance, while keeping it an ad-free platform that respects your data and privacy!
Please consider subscribing below to show your support with a "Plus" badge on your profile and get access to many other features!
A fork of rtexttt by wy
CC Attribution NonCommercial ShareAlike
rtexttt_2
xxxxxxxxxx
const N_WAIT = 50; // Waiting time
const N_ANIM = 25; // Animation duration
const N_FRAMES = 2 * (N_WAIT + N_ANIM); // Total animation frames
let palette = ["#00a000", "#00c000", "#00e000"]; // Particle color palette
let myFont;
let pointCouples = []; // Particle point pairs
let nPoints; // Total number of particle pairs
let s = 4; // Particle size
let inputBox, button; // Input box and button
let currentText = "蛇年快樂"; // Initial text
let targetText = ""; // Target text from user input
function preload() {
// Load font
myFont = loadFont("BoutiqueBitmap9x9_Bold_1.9.ttf");
}
function setup() {
createCanvas(800, 800);
noStroke();
// Create input box and button
inputBox = createInput();
inputBox.position(20, height + 20); // Place below the canvas
inputBox.size(200);
button = createButton("Update Text");
button.position(inputBox.x + inputBox.width + 10, height + 20);
button.mousePressed(updateText); // When button is clicked
// Initialize animation with default text
initializeAnimation(currentText, currentText); // Start with "蛇年快樂"
}
function draw() {
background(20); // Set background color
// Draw each particle's animation
for (let i = 0; i < nPoints; i++) {
let t = timeFunc(pointCouples[i].animVal); // Calculate current animation progress
let p1 = pointCouples[i].p1, p2 = pointCouples[i].p2;
// Use interpolation to calculate particle's current position
let x = lerp(p1.x, p2.x, t);
let y = lerp(p1.y, p2.y, t);
fill(p1.col); // Use initial color
square(x + s, y + s, s); // Draw particle
}
fill(240); // Use white to draw background particles
for (let i = 0; i < nPoints; i++) {
let t = timeFunc(pointCouples[i].animVal); // Calculate current animation progress
let p1 = pointCouples[i].p1, p2 = pointCouples[i].p2;
// Use interpolation to calculate particle's current position
let x = lerp(p1.x, p2.x, t);
let y = lerp(p1.y, p2.y, t);
square(x, y, s); // Draw particle
}
}
// Initialize animation with source and target text
function initializeAnimation(sourceText, targetText) {
pointCouples = []; // Reset particle pairs
// Generate starting and target points
let points1 = textToPoints([sourceText]); // Initial point data
let points2 = textToPoints([targetText]); // Target point data
let animType = ~~random(3); // Randomly select animation type (0, 1, or 2)
// Match initial and target points
for (let i = 0; i < points1.length; i++) {
let shape1 = points1[i];
let shape2 = points2[i] || []; // In case target has fewer shapes
setupPointCouples(shape1, shape2, animType);
}
nPoints = pointCouples.length; // Set total particle count
}
// Update text when button is clicked
function updateText() {
targetText = inputBox.value(); // Get input text
if (targetText.trim() === "") {
console.error("Input text is empty.");
return;
}
initializeAnimation(currentText, targetText); // Map from currentText to targetText
currentText = targetText; // Update current text
}
// Convert text into point cloud data
function textToPoints(txt) {
if (!txt || txt.length === 0) {
console.error("Invalid or empty input for textToPoints");
return [];
}
let points = [];
let pixSize = s * 2;
let txtSize = pixSize * 10;
let w = pixSize * 7;
let h = pixSize * 10;
let m = 0;
for (let l of txt) {
if (l.length > m) m = l.length;
}
let n = txt.length;
let y0 = height / 2 - n * h / 2; // Calculate text's initial position
let colors = [...Array(m)].map(() => Array(n));
for (let j = 0; j < n; j++) {
let l = txt[j];
let x0 = width / 2 - m * w / 2;
let chars = l.split("");
for (let i = 0; i < chars.length; i++) {
let neighborColors = [];
if (i > 0) neighborColors.push(colors[i - 1][j]);
if (j > 0) neighborColors.push(colors[i][j - 1]);
let col;
do {
col = random(palette); // Randomly choose color
} while (neighborColors.indexOf(col) != -1);
colors[i][j] = col;
let ch = chars[i]; // Current character
let grph = makeLetterBuffer(ch, txtSize, w, h);
let letterPoints = [];
for (let x = 0; x < w; x += s) {
for (let y = 0; y < h; y += s) {
let index = 4 * (round(y + s / 2) * w + round(x + s / 2));
let val = grph.pixels[index];
if (val < 20) {
letterPoints.push({ x: x0 + x, y: y0 + y, col: col });
}
}
}
points.push(letterPoints);
grph.remove();
grph = undefined;
x0 += w;
}
y0 += h;
}
return points;
}
// Create buffer for each character
function makeLetterBuffer(ch, size, w, h) {
let grph = createGraphics(w, h);
grph.pixelDensity(1);
grph.textFont(myFont, size);
grph.textAlign(LEFT, TOP);
grph.background(255);
grph.noStroke();
grph.fill(0);
grph.text(ch, 0, 0);
grph.loadPixels();
return grph;
}
// Setup point pairs and handle animation types
function setupPointCouples(shape1, shape2, animType) {
if (!shape1 || !shape2 || shape1.length === 0 || shape2.length === 0) {
console.error("setupPointCouples: Invalid or empty shapes:", shape1, shape2);
return; // Skip if either shape is invalid
}
let nPoints1 = shape1.length;
let nPoints2 = shape2.length;
// Handle mismatched point counts
if (nPoints1 < nPoints2) {
for (let j = 0; j < nPoints2 - nPoints1; j++) {
shape1.push(random(shape1)); // Duplicate random points from shape1
}
} else {
for (let j = 0; j < nPoints1 - nPoints2; j++) {
shape2.push(random(shape2)); // Duplicate random points from shape2
}
}
// Pair points and set animation values
for (let p1 of shape1) {
let idx, minDist = Infinity;
// Find the closest target point
for (let j = 0; j < shape2.length; j++) {
let p2 = shape2[j];
let d = distSquared(p1, p2); // Safe call to distSquared
if (d < minDist) {
idx = j;
minDist = d;
if (d === 0) break;
}
}
let p2 = shape2.splice(idx, 1)[0]; // Remove matched point from shape2
if (!p1 || !p2) {
console.error("setupPointCouples: Invalid point pair:", p1, p2);
continue; // Skip this pair
}
let animVal = (p1.y + p2.y) / 10; // Default animation value
if (animType === 1) {
// Animation Type 1: Based on distance to canvas center
animVal = width * height - mag((p1.x + p2.x) / 2 - width / 2, (p1.y + p2.y) / 2 - height / 2) / 3;
} else if (animType === 2) {
// Animation Type 2: Based on angle
animVal = N_ANIM * (TWO_PI - (atan2((p1.y + p2.y) / 2 - height / 2, (p1.x + p2.x) / 2 - width / 2) + PI));
}
pointCouples.push({
p1: p1,
p2: p2,
animVal: animVal + random(-1, 1) * s
});
}
}
// Calculate squared distance between points
function distSquared(p1, p2) {
if (!p1 || !p2) {
console.error("distSquared: One or both points are undefined:", p1, p2);
return Infinity; // Return a large value to skip this pair
}
return mag(p1.x - p2.x, p1.y - p2.y);
}
// Time function to control animation interpolation
function timeFunc(animVal) {
let x = (frameCount + animVal) % N_FRAMES;
if (x < N_WAIT) return 0;
if (x < N_WAIT + N_ANIM) return easeOutBack((x - N_WAIT) / N_ANIM);
if (x < 2 * N_WAIT + N_ANIM) return 1;
return 1 - easeOutBack((x - 2 * N_WAIT - N_ANIM) / N_ANIM);
}
// Easing function for smooth animation
function easeOutBack(x) {
const c1 = 1.70158;
const c3 = c1 + 1;
return 1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2);
}
See More Shortcuts
Please verify your email to comment
Verify Email