ascii-visualization / index.html
myratmyradov1997's picture
Add 2 files
9275e43 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Кодирование ASCII - Визуализация</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gif.js/0.2.0/gif.js"></script>
<style>
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.ascii-cell {
transition: all 0.3s ease;
}
.ascii-cell.active {
background-color: #3b82f6;
color: white;
transform: scale(1.1);
box-shadow: 0 0 10px rgba(59, 130, 246, 0.7);
}
.code-line {
position: relative;
}
.code-line::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 0;
height: 2px;
background-color: #3b82f6;
transition: width 0.5s ease;
}
.code-line.animating::after {
width: 100%;
}
.binary-digit {
display: inline-block;
transition: all 0.3s ease;
}
.binary-digit.active {
color: #3b82f6;
transform: translateY(-5px);
font-weight: bold;
}
.progress-bar {
height: 4px;
background-color: #e5e7eb;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #3b82f6;
width: 0;
transition: width 0.5s ease;
}
#captureContainer {
position: fixed;
top: -9999px;
left: -9999px;
width: 1000px;
z-index: -1;
}
.download-btn {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 100;
opacity: 0;
transition: opacity 0.3s;
}
.download-btn.show {
opacity: 1;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen font-mono">
<!-- Hidden container for capturing frames -->
<div id="captureContainer"></div>
<!-- Download button (initially hidden) -->
<button id="downloadGifBtn" class="download-btn bg-blue-500 hover:bg-blue-600 text-white px-4 py-3 rounded-full shadow-lg transition">
<i class="fas fa-download mr-2"></i>Скачать GIF
</button>
<div class="container mx-auto px-4 py-8">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Визуализация процесса кодирования</h1>
<p class="text-gray-600">Интерактивная демонстрация преобразования текста в ASCII и двоичный код</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<!-- Input Section -->
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Введите текст для кодирования</h2>
<div class="flex items-center mb-4">
<input type="text" id="inputText" placeholder="Например: Hello"
class="flex-1 border border-gray-300 rounded-l-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
<button id="encodeBtn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-r-md transition">
<i class="fas fa-code mr-2"></i>Кодировать
</button>
</div>
<div class="progress-bar mb-4">
<div id="progressFill" class="progress-fill"></div>
</div>
<div id="codeOutput" class="bg-gray-100 p-4 rounded-md min-h-32">
<p class="text-gray-500 italic">Здесь появится процесс кодирования...</p>
</div>
</div>
<!-- ASCII Table -->
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Таблица ASCII</h2>
<div class="overflow-x-auto">
<table class="w-full border-collapse">
<thead>
<tr class="bg-gray-100">
<th class="border p-2">Dec</th>
<th class="border p-2">Hex</th>
<th class="border p-2">Char</th>
<th class="border p-2">Binary</th>
</tr>
</thead>
<tbody id="asciiTableBody">
<!-- ASCII table will be populated here -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Binary Visualization -->
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Двоичное представление</h2>
<div id="binaryVisualization" class="text-center text-2xl font-mono p-4 bg-gray-100 rounded-md">
<p class="text-gray-500">Введите текст для отображения двоичного кода</p>
</div>
</div>
<!-- Encoding Steps -->
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Процесс кодирования</h2>
<div id="encodingSteps" class="space-y-4">
<div class="step p-4 border-l-4 border-blue-500 bg-blue-50">
<h3 class="font-medium text-gray-800">1. Ввод текста</h3>
<p class="text-gray-600">Пользователь вводит текст для кодирования</p>
</div>
<div class="step p-4 border-l-4 border-gray-300">
<h3 class="font-medium text-gray-800">2. Преобразование в ASCII</h3>
<p class="text-gray-600">Каждый символ преобразуется в соответствующий код ASCII</p>
</div>
<div class="step p-4 border-l-4 border-gray-300">
<h3 class="font-medium text-gray-800">3. Преобразование в двоичный код</h3>
<p class="text-gray-600">Код ASCII преобразуется в 8-битное двоичное число</p>
</div>
<div class="step p-4 border-l-4 border-gray-300">
<h3 class="font-medium text-gray-800">4. Отображение результата</h3>
<p class="text-gray-600">Отображается полный двоичный код введённого текста</p>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize ASCII table
const asciiTableBody = document.getElementById('asciiTableBody');
for (let i = 32; i < 128; i++) {
const row = document.createElement('tr');
row.className = 'ascii-row hover:bg-gray-50';
row.innerHTML = `
<td class="border p-2 ascii-dec">${i}</td>
<td class="border p-2 ascii-hex">${i.toString(16).toUpperCase()}</td>
<td class="border p-2 ascii-char text-center">${String.fromCharCode(i)}</td>
<td class="border p-2 ascii-bin">${i.toString(2).padStart(8, '0')}</td>
`;
asciiTableBody.appendChild(row);
}
// Variables for GIF creation
let gif = null;
let frames = [];
let frameCount = 0;
const downloadBtn = document.getElementById('downloadGifBtn');
// Setup GIF download button
downloadBtn.addEventListener('click', function() {
if (frames.length > 0) {
createGifFromFrames();
}
});
// Encoding function
document.getElementById('encodeBtn').addEventListener('click', function() {
const inputText = document.getElementById('inputText').value.trim();
if (!inputText) return;
// Reset everything
resetVisualization();
// Prepare for new recording
frames = [];
frameCount = 0;
// Show encoding process
animateEncoding(inputText);
});
function resetVisualization() {
document.querySelectorAll('.ascii-cell').forEach(cell => {
cell.classList.remove('active');
});
document.querySelectorAll('.step').forEach((step, index) => {
step.className = 'step p-4 border-l-4 ' +
(index === 0 ? 'border-blue-500 bg-blue-50' : 'border-gray-300');
});
document.getElementById('binaryVisualization').innerHTML = '<p class="text-gray-500">Введите текст для отображения двоичного кода</p>';
document.getElementById('progressFill').style.width = '0';
document.getElementById('codeOutput').innerHTML = '<p class="text-gray-500 italic">Здесь появится процесс кодирования...</p>';
downloadBtn.classList.remove('show');
}
function captureFrame() {
const captureContainer = document.getElementById('captureContainer');
const visualElements = document.querySelector('.container').cloneNode(true);
// Clean up cloned element for capture
visualElements.querySelectorAll('.ascii-cell.active').forEach(cell => {
cell.classList.remove('active');
});
captureContainer.innerHTML = '';
captureContainer.appendChild(visualElements);
html2canvas(captureContainer).then(canvas => {
frames.push(canvas);
frameCount++;
// Show download button after first frame is captured
if (frameCount === 1) {
setTimeout(() => {
downloadBtn.classList.add('show');
}, 500);
}
});
}
function createGifFromFrames() {
downloadBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Создание GIF...';
// Create GIF with good quality settings
gif = new GIF({
workers: 2,
quality: 10,
width: 1000,
height: Math.min(1000, frames[0].height * (1000 / frames[0].width)),
workerScript: 'https://cdnjs.cloudflare.com/ajax/libs/gif.js/0.2.0/gif.worker.js'
});
// Add each frame to GIF
const frameDelay = 500; // 0.5s delay between frames
frames.forEach((frame, index) => {
// Skip some frames if there are too many to keep GIF size reasonable
if (index % 2 === 0 || index === frames.length - 1) {
gif.addFrame(frame, {delay: frameDelay, copy: true});
}
});
gif.on('finished', function(blob) {
// Create download link
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'ascii_encoding_animation.gif';
a.click();
URL.revokeObjectURL(url);
downloadBtn.innerHTML = '<i class="fas fa-download mr-2"></i>Скачать GIF';
});
gif.render();
}
function animateEncoding(text) {
const steps = document.querySelectorAll('.step');
const progressFill = document.getElementById('progressFill');
const binaryVisualization = document.getElementById('binaryVisualization');
const codeOutput = document.getElementById('codeOutput');
// Initial capture
setTimeout(captureFrame, 300);
// Step 1: Input text (already shown)
setTimeout(() => {
// Step 2: Convert to ASCII
steps[1].className = 'step p-4 border-l-4 border-blue-500 bg-blue-50';
progressFill.style.width = '25%';
captureFrame();
let asciiOutput = '';
text.split('').forEach((char, index) => {
setTimeout(() => {
const code = char.charCodeAt(0);
asciiOutput += `<div class="code-line mb-2">'${char}' → ${code} (ASCII)</div>`;
codeOutput.innerHTML = asciiOutput;
// Highlight in ASCII table
const asciiRows = document.querySelectorAll('.ascii-row');
asciiRows.forEach(row => {
const decCell = row.querySelector('.ascii-dec');
if (decCell && parseInt(decCell.textContent) === code) {
row.querySelectorAll('td').forEach(cell => {
cell.classList.add('active', 'ascii-cell');
});
setTimeout(() => {
row.querySelectorAll('td').forEach(cell => {
cell.classList.remove('active');
});
}, 1000);
}
});
// Animate code line
const lines = document.querySelectorAll('.code-line');
lines[lines.length - 1].classList.add('animating');
setTimeout(() => {
lines[lines.length - 1].classList.remove('animating');
}, 500);
// Capture frame after character is processed
setTimeout(captureFrame, 100);
if (index === text.length - 1) {
setTimeout(() => {
// Step 3: Convert to binary
steps[2].className = 'step p-4 border-l-4 border-blue-500 bg-blue-50';
progressFill.style.width = '50%';
captureFrame();
let binaryOutput = '';
text.split('').forEach((char, charIndex) => {
setTimeout(() => {
const code = char.charCodeAt(0);
const binary = code.toString(2).padStart(8, '0');
binaryOutput += `<div class="code-line mb-2">${code}${binary} (binary)</div>`;
codeOutput.innerHTML = asciiOutput + binaryOutput;
// Animate binary digits
const binaryDigits = binary.split('');
let binaryHTML = '';
binaryDigits.forEach((digit, digitIndex) => {
binaryHTML += `<span class="binary-digit">${digit}</span>`;
});
// Show binary visualization
if (charIndex === 0) {
binaryVisualization.innerHTML = '';
}
const charDiv = document.createElement('div');
charDiv.className = 'mb-2';
charDiv.innerHTML = `<span class="mr-2">'${char}':</span>${binaryHTML}`;
binaryVisualization.appendChild(charDiv);
// Animate each digit
const digits = charDiv.querySelectorAll('.binary-digit');
digits.forEach((digit, i) => {
setTimeout(() => {
digit.classList.add('active');
setTimeout(() => {
digit.classList.remove('active');
// Capture frame after digit animation
if (i === digits.length - 1) {
setTimeout(captureFrame, 100);
}
}, 300);
}, i * 100);
});
// Animate code line
const lines = document.querySelectorAll('.code-line');
lines[lines.length - 1].classList.add('animating');
setTimeout(() => {
lines[lines.length - 1].classList.remove('animating');
}, 500);
if (charIndex === text.length - 1) {
setTimeout(() => {
// Step 4: Show final result
steps[3].className = 'step p-4 border-l-4 border-blue-500 bg-blue-50';
progressFill.style.width = '100%';
// Show full binary representation
let fullBinary = '';
text.split('').forEach(char => {
fullBinary += char.charCodeAt(0).toString(2).padStart(8, '0') + ' ';
});
binaryVisualization.innerHTML = `
<div class="text-left mb-4">
<p class="font-medium">Исходный текст: <span class="text-blue-500">"${text}"</span></p>
<p class="font-medium">Двоичное представление:</p>
</div>
<div class="bg-gray-800 text-green-400 p-4 rounded-md text-left overflow-x-auto">
${fullBinary.trim()}
</div>
`;
// Final capture
setTimeout(captureFrame, 500);
}, 1000);
}
}, charIndex * 1200);
});
}, 1000);
}
}, index * 800);
});
}, 1000);
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>