DanielKruzo's picture
Кнопка "Download" не працює.
ba09963 verified
Raw History Blame Contribute Delete
11.9 kB
document.addEventListener('DOMContentLoaded', function() {
// Initialize UI elements
const dropArea = document.getElementById('drop-area');
const fileInput = document.getElementById('file-input');
const convertBtn = document.getElementById('convert-btn');
const convertText = document.getElementById('convert-text');
const convertSpinner = document.getElementById('convert-spinner');
const resultsSection = document.getElementById('results');
const originalContainer = document.getElementById('original-container');
const resultContainer = document.getElementById('result-container');
const svgCode = document.getElementById('svg-code');
const downloadBtn = document.getElementById('download-btn');
const copyBtn = document.getElementById('copy-btn');
const fileInfo = document.getElementById('file-info');
const zoomControls = document.getElementById('zoom-controls');
const zoomInBtn = document.getElementById('zoom-in');
const zoomOutBtn = document.getElementById('zoom-out');
const zoomResetBtn = document.getElementById('zoom-reset');
const colorModeToggle = document.getElementById('color-mode');
const colorModeLabel = document.getElementById('color-mode-label');
const colorSettings = document.getElementById('color-settings');
const colorCount = document.getElementById('color-count');
const colorCountValue = document.getElementById('color-count-value');
const detailLevel = document.getElementById('detail-level');
const smoothness = document.getElementById('smoothness');
const smoothnessValue = document.getElementById('smoothness-value');
const outputFormat = document.getElementById('output-format');
let uploadedFile = null;
let scale = 1;
let canvas = null;
let svgPreview = null;
let isDragging = false;
let startPos = { x: 0, y: 0 };
let translate = { x: 0, y: 0 };
// Initialize event listeners
initEventListeners();
function initEventListeners() {
// Drag and drop handlers
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false);
document.body.addEventListener(eventName, preventDefaults, false);
});
['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, unhighlight, false);
});
dropArea.addEventListener('drop', handleDrop, false);
fileInput.addEventListener('change', handleFiles, false);
convertBtn.addEventListener('click', convertToSVG);
downloadBtn.addEventListener('click', downloadSVG);
copyBtn.addEventListener('click', copySVGCode);
// Color mode toggle
colorModeToggle.addEventListener('change', toggleColorMode);
colorCount.addEventListener('input', updateColorCount);
smoothness.addEventListener('input', updateSmoothness);
// Zoom controls
zoomInBtn.addEventListener('click', () => zoomImage(1.2));
zoomOutBtn.addEventListener('click', () => zoomImage(0.8));
zoomResetBtn.addEventListener('click', resetZoom);
// SVG preview interactions
resultContainer.addEventListener('mousedown', startDrag);
document.addEventListener('mousemove', dragImage);
document.addEventListener('mouseup', endDrag);
resultContainer.addEventListener('touchstart', startDrag);
document.addEventListener('touchmove', dragImage);
document.addEventListener('touchend', endDrag);
}
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
function highlight() {
dropArea.classList.add('highlight');
}
function unhighlight() {
dropArea.classList.remove('highlight');
}
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
handleFiles({ target: { files } });
}
function handleFiles(e) {
const files = e.target.files;
if (files.length) {
const file = files[0];
if (!file.type.match('image.*')) {
alert('Please upload an image file (JPG, PNG etc.)');
return;
}
uploadedFile = file;
displayOriginalImage(uploadedFile);
}
}
function displayOriginalImage(file) {
const reader = new FileReader();
reader.onload = function(e) {
const img = document.createElement('img');
img.onload = function() {
URL.revokeObjectURL(this.src);
updateFileInfo(file, this.width, this.height);
};
img.src = e.target.result;
img.className = 'max-w-full max-h-full';
originalContainer.innerHTML = '';
originalContainer.appendChild(img);
};
reader.readAsDataURL(file);
}
function updateFileInfo(file, width, height) {
const sizeMB = (file.size / (1024 * 1024)).toFixed(2);
fileInfo.innerHTML = `
${file.name} | ${width}×${height}px | ${sizeMB}MB
`;
}
function convertToSVG() {
if (!uploadedFile) {
showAlert('Please upload an image first');
return;
}
// Show loading state
convertBtn.disabled = true;
convertText.textContent = 'Processing...';
convertSpinner.classList.remove('hidden');
// Process image (simplified example - in production you would use a proper vectorization algorithm)
setTimeout(() => {
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// Get conversion settings
const isColor = colorModeToggle.checked;
const colorCountVal = parseInt(colorCount.value);
const smoothnessVal = parseInt(smoothness.value);
const detailLevelVal = detailLevel.value;
// Process image based on settings (simplified)
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
if (!isColor) {
// Monochrome conversion
const threshold = 128; // Default threshold
for (let i = 0; i < data.length; i += 4) {
const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
const val = avg > threshold ? 255 : 0;
data[i] = data[i + 1] = data[i + 2] = val;
}
} else {
// Color quantization (simplified)
// In a real app, you would use a proper quantization algorithm
const step = Math.floor(256 / colorCountVal);
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.floor(data[i] / step) * step; // R
data[i+1] = Math.floor(data[i+1] / step) * step; // G
data[i+2] = Math.floor(data[i+2] / step) * step; // B
}
}
ctx.putImageData(imageData, 0, 0);
// Generate SVG (simplified - real implementation would use vector paths)
const canvasDataURL = canvas.toDataURL('image/png');
const svg = `<svg viewBox="0 0 ${img.width} ${img.height}" xmlns="http://www.w3.org/2000/svg">
<image href="${canvasDataURL}" width="${img.width}" height="${img.height}"/>
</svg>`;
// Display result
displaySVGResult(svg, img.width, img.height);
// Reset button state
convertBtn.disabled = false;
convertText.textContent = 'Convert to Vector';
convertSpinner.classList.add('hidden');
};
img.src = URL.createObjectURL(uploadedFile);
}, 500); // Simulate processing time
}
function displaySVGResult(svg, width, height) {
resultContainer.innerHTML = '';
const svgBlob = new Blob([svg], {type: 'image/svg+xml'});
const svgUrl = URL.createObjectURL(svgBlob);
svgPreview = document.createElement('img');
svgPreview.src = svgUrl;
svgPreview.className = 'max-w-full max-h-full transform origin-center';
svgPreview.style.transform = `scale(${scale}) translate(${translate.x}px, ${translate.y}px)`;
resultContainer.appendChild(svgPreview);
svgCode.textContent = svg;
resultsSection.classList.remove('hidden');
zoomControls.classList.remove('hidden');
// Scroll to results
resultsSection.scrollIntoView({ behavior: 'smooth' });
}
function toggleColorMode() {
const isColor = colorModeToggle.checked;
colorModeLabel.textContent = isColor ? 'Color' : 'Monochrome';
colorSettings.style.display = isColor ? 'block' : 'none';
}
function updateColorCount() {
colorCountValue.textContent = colorCount.value;
}
function updateSmoothness() {
smoothnessValue.textContent = smoothness.value;
}
function zoomImage(factor) {
scale *= factor;
updateImageTransform();
}
function resetZoom() {
scale = 1;
translate = { x: 0, y: 0 };
updateImageTransform();
}
function startDrag(e) {
if (!svgPreview) return;
isDragging = true;
startPos = {
x: e.clientX || e.touches[0].clientX,
y: e.clientY || e.touches[0].clientY
};
resultContainer.classList.add('dragging');
e.preventDefault();
}
function dragImage(e) {
if (!isDragging || !svgPreview) return;
const currentPos = {
x: e.clientX || e.touches[0].clientX,
y: e.clientY || e.touches[0].clientY
};
translate.x += (currentPos.x - startPos.x) / scale;
translate.y += (currentPos.y - startPos.y) / scale;
startPos = currentPos;
updateImageTransform();
e.preventDefault();
}
function endDrag() {
isDragging = false;
resultContainer.classList.remove('dragging');
}
function updateImageTransform() {
if (svgPreview) {
svgPreview.style.transform = `scale(${scale}) translate(${translate.x}px, ${translate.y}px)`;
}
}
function showAlert(message, type = 'error') {
const bgColor = type === 'error' ? 'bg-red-100 border-red-500 text-red-700' : 'bg-green-100 border-green-500 text-green-700';
const alert = document.createElement('div');
alert.className = `fixed top-4 right-4 ${bgColor} border-l-4 p-4 rounded shadow-lg z-50`;
alert.innerHTML = `
<div class="flex items-center gap-2">
<i data-feather="alert-triangle"></i>
<span>${message}</span>
</div>
`;
document.body.appendChild(alert);
feather.replace();
setTimeout(() => {
alert.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => alert.remove(), 300);
}, 3000);
}
});