Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save colorincode/46ad47e80d00c2358c5b452aaa16eaca to your computer and use it in GitHub Desktop.
Save colorincode/46ad47e80d00c2358c5b452aaa16eaca to your computer and use it in GitHub Desktop.
measurer
import gsap from "https://esm.sh/gsap";
import { TextPlugin } from "https://esm.sh/gsap/all";
import { EasePack } from "https://esm.sh/gsap/EasePack";
import confetti from "https://esm.sh/canvas-confetti";
gsap.registerPlugin(TextPlugin, EasePack);
let currentStep = 1;
const totalSteps = 10;
const quizData = {};
let unit = 'inches';
const steps = document.querySelectorAll('.step');
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');
const submitBtn = document.getElementById('submit-btn');
const resultDiv = document.getElementById('result');
const unitInputs = document.querySelectorAll('input[name="unit"]');
const toCm = (value) => unit === 'inches' ? value * 2.54 : value;
const toKg = (value) => unit === 'inches' ? value * 0.453592 : value;
unitInputs.forEach(input => {
input.addEventListener('change', () => {
unit = input.value;
});
});
function animateStepTransition(outStep, inStep) {
gsap.timeline()
.to(outStep, { opacity: 0, x: -50, duration: 0.3, onComplete: () => outStep.style.display = 'none' })
.fromTo(inStep, { opacity: 0, x: 50 }, { opacity: 1, x: 0, duration: 0.3, onStart: () => inStep.style.display = 'block' });
}
function updateButtons() {
prevBtn.disabled = currentStep === 1;
nextBtn.style.display = currentStep === totalSteps ? 'none' : 'inline-block';
submitBtn.style.display = currentStep === totalSteps ? 'inline-block' : 'none';
}
function validateStep() {
const input = steps[currentStep - 1].querySelector('input, select');
if (currentStep <= 9) {
const valueRaw = input.value ? parseFloat(input.value) : NaN;
if (isNaN(valueRaw)) {
alert(`Please enter a valid ${currentStep === 1 ? 'height' : currentStep === 2 ? 'arm span' : currentStep === 3 ? 'nose size' : currentStep === 4 ? 'finger length' : currentStep === 5 ? 'age' : currentStep === 6 ? 'weight' : currentStep === 7 ? 'number of partners' : currentStep === 8 ? 'hairiness' : 'shoe size'}.`);
return false;
}
let value;
switch (currentStep) {
case 1: // Height
value = unit === 'inches' ? Math.max(47, Math.min(98, valueRaw)) : Math.max(120, Math.min(250, valueRaw));
quizData.height = toCm(value);
// console.log(`Height stored: ${quizData.height} cm (clamped from ${valueRaw} ${unit})`);
break;
case 2: // Arm Span
value = unit === 'inches' ? Math.max(43, Math.min(106, valueRaw)) : Math.max(110, Math.min(270, valueRaw));
quizData.armSpan = toCm(value);
// console.log(`Arm Span stored: ${quizData.armSpan} cm (clamped from ${valueRaw} ${unit})`);
break;
case 3: // Nose Size
value = unit === 'inches' ? Math.max(0.8, Math.min(3.5, valueRaw)) : Math.max(2, Math.min(9, valueRaw));
quizData.nose = toCm(value);
// console.log(`Nose stored: ${quizData.nose} cm (clamped from ${valueRaw} ${unit})`);
break;
case 4: // Finger Lengths
const indexInput = document.getElementById('index-finger');
const ringInput = document.getElementById('ring-finger');
const indexRaw = indexInput.value ? parseFloat(indexInput.value) : NaN;
const ringRaw = ringInput.value ? parseFloat(ringInput.value) : NaN;
if (isNaN(indexRaw)) {
alert('Please enter a valid index finger length.');
return false;
}
if (isNaN(ringRaw)) {
alert('Please enter a valid ring finger length.');
return false;
}
const index = unit === 'inches' ? Math.max(1.6, Math.min(4.7, indexRaw)) : Math.max(4, Math.min(12, indexRaw));
const ring = unit === 'inches' ? Math.max(1.6, Math.min(4.7, ringRaw)) : Math.max(4, Math.min(12, ringRaw));
quizData.indexFinger = toCm(index);
quizData.ringFinger = toCm(ring);
// console.log(`Index Finger stored: ${quizData.indexFinger} cm (clamped from ${indexRaw} ${unit}), Ring Finger stored: ${quizData.ringFinger} cm (clamped from ${ringRaw} ${unit})`);
break;
case 5: // Age
value = Math.max(18, Math.min(100, valueRaw));
quizData.age = value;
// console.log(`Age stored: ${quizData.age} years (clamped from ${valueRaw})`);
break;
case 6: // Weight
value = unit === 'inches' ? Math.max(80, Math.min(500, valueRaw)) : Math.max(36, Math.min(227, valueRaw));
quizData.weight = toKg(value);
// console.log(`Weight stored: ${quizData.weight} kg (clamped from ${valueRaw} ${unit === 'inches' ? 'lbs' : 'kg'})`);
break;
case 7: // Number of Partners (Decoy)
value = Math.max(0, Math.min(100, valueRaw));
quizData.partners = value;
// console.log(`Partners stored: ${quizData.partners} (clamped from ${valueRaw})`);
break;
case 8: // Hairiness
value = Math.max(1, Math.min(5, valueRaw));
quizData.hairiness = value;
// console.log(`Hairiness stored: ${quizData.hairiness} (clamped from ${valueRaw})`);
break;
case 9: // Shoe Size (Decoy)
value = Math.max(4, Math.min(18, valueRaw));
quizData.shoeSize = value;
// console.log(`Shoe Size stored: ${quizData.shoeSize} (clamped from ${valueRaw})`);
break;
}
} else if (currentStep === 10) {
const value = input.value.trim();
if (!value) {
alert('Please enter your first name or nickname.');
return false;
}
quizData.nickname = value;
// console.log(`Nickname stored: ${quizData.nickname}`);
}
return true;
}
prevBtn.addEventListener('click', () => {
if (currentStep > 1) {
const current = steps[currentStep - 1];
const previous = steps[currentStep - 2];
currentStep--;
animateStepTransition(current, previous);
updateButtons();
}
});
nextBtn.addEventListener('click', () => {
if (validateStep() && currentStep < totalSteps) {
const current = steps[currentStep - 1];
const next = steps[currentStep];
currentStep++;
animateStepTransition(current, next);
updateButtons();
}
});
submitBtn.addEventListener('click', () => {
if (validateStep()) {
const { height, armSpan, nose, indexFinger, ringFinger, age, weight, hairiness, nickname } = quizData;
// console.log(`Final Values - Height: ${height}, Arm Span: ${armSpan}, Nose: ${nose}, Index: ${indexFinger}, Ring: ${ringFinger}, Age: ${age}, Weight: ${weight}, Hairiness: ${hairiness}, Nickname: ${nickname}`);
const splBase = (0.09 * height + 0.09 * armSpan + 2.8 * nose) / 3;
const splAge = -0.01 * (age - 30);
const splWeight = -0.005 * (weight - 68);
const splHairiness = 0.1 * (hairiness - 3);
const digitRatio = indexFinger / ringFinger;
const splDigitOffset = digitRatio < 1 ? 1.5 : 0;
const splFinal = splBase + splAge + splWeight + splHairiness + splDigitOffset;
// console.log(`SPL Breakdown - Base: ${splBase}, Age: ${splAge}, Weight: ${splWeight}, Hairiness: ${splHairiness}, Digit Offset: ${splDigitOffset}, Final: ${splFinal}`);
let category, message, imagePlaceholder;
const scalar = 2;
const banana = confetti.shapeFromText({ text: '๐ŸŒ', scalar });
const eggplant = confetti.shapeFromText({ text: '๐Ÿ†', scalar });
if (splFinal < 12) {
category = 'small';
message = `You got smol. Here is a joke for your troubles: <br/>
there's these 3 lil dudes outside of the guinness book of world records, <br/>
first one says I'm gonna get the record for the smallest hands. walks in, comes back out hands in the air says boys i did it.<br/>
second one says I'm gonna get the record for the smallest feet. walks in, little bitch skips back out, fellas i got the record.<br/>
third one says i'm gonna get the record for the smallest dick <br/>
couple minutes later walks out sad as hell looking at the ground, says
'Bros, who TF is ${nickname}?' <br/>
<a href="https://x.com/ken_wheeler"> joke from @kenwheeler </a>
`;
imagePlaceholder = '<img src="./assets/small-meme.png" alt="Small Result Meme" class="result-image">';
} else if (splFinal >= 12 && splFinal < 14) {
category = 'medium';
message = `${nickname}, you're rocking an average size. Perfectly solid!`;
imagePlaceholder = '<img src="./assets/medium-meme.png" alt="Medium Result Meme" class="result-image">';
confetti({
shapes: [banana],
scalar,
particleCount: 60,
spread: 100,
colors: ['#ff0000', '#00ff00', '#0000ff']
});
} else {
category = 'large';
message = `Wow ${nickname}, you're packing a schlong a dong!`;
imagePlaceholder = '<img src="./assets/large-meme.png" alt="Large Result Meme" class="result-image">';
confetti({
shapes: [eggplant],
scalar,
particleCount: 200,
spread: 200,
colors: ['#ff0000', '#00ff00', '#0000ff']
});
}
const sizeText = `Estimated Size: ${splFinal.toFixed(1)} cm (${(splFinal / 2.54).toFixed(1)} in)`;
const shareText = `${message} ${sizeText} Check out my result from the ultimate dick measuring quiz! https://toycode.tech`;
const shareUrl = `https://x.com/intent/tweet?text=${encodeURIComponent(shareText)}`;
resultDiv.innerHTML = `
<div class="result-card">
${imagePlaceholder}
<h3>${message}</h3>
<p>${sizeText}</p>
<a href="${shareUrl}" target="_blank" class="share-btn">Share on X</a>
</div>
`;
gsap.from(resultDiv, { opacity: 0, y: 20, duration: 0.5 });
}
});
updateButtons();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment