fluffy-mindscapes / script.js
Defkhan5960's picture
try to use same desing for clouds in the attaching media!
4c7a4fd verified
document.addEventListener('DOMContentLoaded', async function() {
// Initialize cloud data
const cloudData = [
{ text: "Happiness", percentage: 0 },
{ text: "Adventure", percentage: 0 },
{ text: "Creativity", percentage: 0 },
{ text: "Friendship", percentage: 0 },
{ text: "Success", percentage: 0 },
{ text: "Love", percentage: 0 },
{ text: "Freedom", percentage: 0 },
{ text: "Peace", percentage: 0 },
{ text: "Growth", percentage: 0 },
{ text: "Discovery", percentage: 0 }
];
const cloudContainer = document.getElementById('cloud-container');
const textInput = document.getElementById('text-input');
const analyzeBtn = document.getElementById('analyze-btn');
const resultsSection = document.getElementById('results');
const similarityResults = document.getElementById('similarity-results');
// Load the Universal Sentence Encoder
let model;
try {
model = await use.load();
console.log('Model loaded successfully');
} catch (err) {
console.error('Failed to load model:', err);
return;
}
// Create initial clouds
createClouds();
// Add event listeners
analyzeBtn.addEventListener('click', () => {
analyzeBtn.disabled = true;
analyzeBtn.innerHTML = '<i data-feather="loader" class="animate-spin"></i>';
feather.replace();
analyzeText().finally(() => {
analyzeBtn.disabled = false;
analyzeBtn.innerHTML = '<i data-feather="search"></i>';
feather.replace();
});
});
textInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
analyzeBtn.click();
}
});
function createClouds() {
cloudContainer.innerHTML = '';
const containerWidth = cloudContainer.offsetWidth;
const containerHeight = cloudContainer.offsetHeight;
// Create a circular layout for initial clouds
const centerX = containerWidth / 2;
const centerY = containerHeight / 2;
const radius = Math.min(containerWidth, containerHeight) * 0.35;
cloudData.forEach((cloud, i) => {
const angle = (i / cloudData.length) * Math.PI * 2;
const x = centerX + Math.cos(angle) * radius;
const y = centerY + Math.sin(angle) * radius;
// Create cloud with base size
createCloud(cloud, x, y, 40);
});
}
function createCloud(data, x, y, baseSize) {
const cloud = document.createElement('custom-cloud');
cloud.setAttribute('text', data.text);
cloud.setAttribute('percentage', data.percentage);
// Position the cloud
cloud.style.left = `${x}px`;
cloud.style.top = `${y}px`;
cloudContainer.appendChild(cloud);
return cloud;
}
async function analyzeText() {
const inputText = textInput.value.trim();
if (!inputText) {
alert('Please enter some text to analyze');
return;
}
try {
// Generate embeddings for input text and cloud texts
const inputEmbedding = await model.embed([inputText]);
const cloudTexts = cloudData.map(c => c.text);
const cloudEmbeddings = await model.embed(cloudTexts);
// Calculate cosine similarity between input and each cloud text
const inputArray = await inputEmbedding.array();
const cloudArrays = await cloudEmbeddings.array();
const similarities = [];
for (let i = 0; i < cloudData.length; i++) {
const similarity = cosineSimilarity(inputArray[0], cloudArrays[i]);
const percentage = Math.round(similarity * 100);
cloudData[i].percentage = percentage;
similarities.push({ text: cloudData[i].text, percentage });
}
// Sort by percentage descending
similarities.sort((a, b) => b.percentage - a.percentage);
// Update UI with results
updateClouds();
showResults(inputText, similarities);
} catch (err) {
console.error('Error analyzing text:', err);
resultsSection.classList.add('hidden');
alert('An error occurred while analyzing your text. Please try again.');
throw err; // Re-throw to ensure button state is reset
}
}
function updateClouds() {
cloudContainer.innerHTML = '';
const containerWidth = cloudContainer.offsetWidth;
const containerHeight = cloudContainer.offsetHeight;
// Sort clouds by percentage (highest first)
const sortedClouds = [...cloudData].sort((a, b) => b.percentage - a.percentage);
// Position clouds in a circular layout
const centerX = containerWidth / 2;
const centerY = containerHeight / 2;
const radius = Math.min(containerWidth, containerHeight) * 0.35;
sortedClouds.forEach((cloud, i) => {
// Calculate angle for positioning
const angle = (i / sortedClouds.length) * Math.PI * 2;
// Calculate position with some randomness for a natural look
const randomOffset = 30;
const x = centerX + Math.cos(angle) * (radius + (Math.random() * randomOffset - randomOffset/2));
const y = centerY + Math.sin(angle) * (radius + (Math.random() * randomOffset - randomOffset/2));
// Create cloud with size based on percentage
const baseSize = 40 + (cloud.percentage * 0.8);
createCloud(cloud, x, y, baseSize);
});
}
function showResults(inputText, similarities) {
resultsSection.classList.remove('hidden');
similarityResults.innerHTML = '';
const heading = document.createElement('h3');
heading.className = 'font-medium text-lg mb-2';
heading.textContent = `How "${inputText}" relates to our concepts:`;
similarityResults.appendChild(heading);
similarities.forEach(item => {
const resultItem = document.createElement('div');
resultItem.className = 'flex items-center justify-between';
const textSpan = document.createElement('span');
textSpan.className = 'text-gray-700';
textSpan.textContent = item.text;
const percentageBar = document.createElement('div');
percentageBar.className = 'flex items-center w-1/2';
const barContainer = document.createElement('div');
barContainer.className = 'flex-1 bg-gray-200 rounded-full h-4 mx-2';
const bar = document.createElement('div');
bar.className = 'bg-blue-500 h-4 rounded-full';
bar.style.width = `${item.percentage}%`;
const percentageText = document.createElement('span');
percentageText.className = 'text-gray-600 w-12 text-right';
percentageText.textContent = `${item.percentage}%`;
barContainer.appendChild(bar);
percentageBar.appendChild(barContainer);
percentageBar.appendChild(percentageText);
resultItem.appendChild(textSpan);
resultItem.appendChild(percentageBar);
similarityResults.appendChild(resultItem);
});
}
// Helper function to calculate cosine similarity
function cosineSimilarity(vecA, vecB) {
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < vecA.length; i++) {
dotProduct += vecA[i] * vecB[i];
normA += vecA[i] * vecA[i];
normB += vecB[i] * vecB[i];
}
normA = Math.sqrt(normA);
normB = Math.sqrt(normB);
return dotProduct / (normA * normB);
}
// Handle window resize
window.addEventListener('resize', () => {
if (cloudData.some(c => c.percentage > 0)) {
updateClouds();
} else {
createClouds();
}
});
});