|
|
<!DOCTYPE html> |
|
|
<html lang="ar" dir="rtl"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title data-lang-key="pageTitle">SkyData - أداة إزالة الخلفية</title> |
|
|
<link rel="icon" href="/favicon.ico" type="image/x-icon"> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"> |
|
|
|
|
|
<style> |
|
|
:root { |
|
|
--primary-color: #007bff; |
|
|
--primary-hover: #0056b3; |
|
|
--glow-color-1: #6366f1; |
|
|
--glow-color-2: #ec4899; |
|
|
--glow-color-3: #f59e0b; |
|
|
--dark-bg: #0d0d1a; |
|
|
--bg-surface: #1a1a2e; |
|
|
--text-color: #e0e0e0; |
|
|
--text-muted: #aaa; |
|
|
--border-color: #333; |
|
|
--error-color: #EF665B; |
|
|
--success-color: #28a745; |
|
|
} |
|
|
* { |
|
|
box-sizing: border-box; |
|
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
|
|
tap-highlight-color: rgba(0, 0, 0, 0); |
|
|
} |
|
|
#app-container { |
|
|
width: 100%; |
|
|
overflow-x: hidden; |
|
|
position: relative; |
|
|
transform: translate3d(0, 0, 0); |
|
|
min-height: 100vh; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
} |
|
|
html { } |
|
|
body { |
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
|
direction: rtl; |
|
|
background-color: var(--dark-bg); |
|
|
color: var(--text-color); |
|
|
margin: 0; padding: 0; |
|
|
} |
|
|
body::before { |
|
|
content: ''; |
|
|
position: fixed; |
|
|
top: 0; left: 0; right: 0; bottom: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
background: linear-gradient( |
|
|
135deg, |
|
|
rgba(var(--glow-color-1), 0.15), |
|
|
rgba(var(--glow-color-2), 0.1), |
|
|
rgba(var(--glow-color-3), 0.15) |
|
|
); |
|
|
background-size: 400% 400%; |
|
|
animation: glowingBackground 20s ease infinite; |
|
|
z-index: -1; |
|
|
filter: blur(50px); |
|
|
} |
|
|
@keyframes glowingBackground { |
|
|
0% { background-position: 0% 50%; } |
|
|
50% { background-position: 100% 50%; } |
|
|
100% { background-position: 0% 50%; } |
|
|
} |
|
|
|
|
|
main { |
|
|
flex-grow: 1; |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
padding: 30px 0; |
|
|
} |
|
|
.main-wrapper { |
|
|
max-width: 400px; |
|
|
width: 95%; |
|
|
} |
|
|
.form { |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
gap: 15px; |
|
|
padding: 30px; |
|
|
border-radius: 10px; |
|
|
position: relative; |
|
|
background-color: var(--bg-surface); |
|
|
color: var(--text-color); |
|
|
border: 1px solid var(--border-color); |
|
|
box-shadow: 0 5px 15px rgba(0,0,0,0.5); |
|
|
animation: fadeIn 0.5s ease-out; |
|
|
} |
|
|
.title { |
|
|
font-size: 24px; |
|
|
font-weight: 600; |
|
|
letter-spacing: -1px; |
|
|
position: relative; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
color: var(--primary-color); |
|
|
margin-bottom: 5px; |
|
|
padding-right: 30px; |
|
|
} |
|
|
.title::before, .title::after { |
|
|
position: absolute; |
|
|
content: ""; |
|
|
height: 16px; |
|
|
width: 16px; |
|
|
border-radius: 50%; |
|
|
right: 0px; |
|
|
background-color: var(--primary-color); |
|
|
} |
|
|
.title::after { animation: pulse 1s linear infinite; } |
|
|
.message-intro { |
|
|
font-size: 14.5px; |
|
|
color: var(--text-muted); |
|
|
margin-bottom: 10px; |
|
|
text-align: right; |
|
|
} |
|
|
.submit { |
|
|
border: none; |
|
|
outline: none; |
|
|
padding: 14px; |
|
|
border-radius: 8px; |
|
|
color: #fff; |
|
|
font-size: 1.2em; |
|
|
font-weight: bold; |
|
|
background-color: var(--primary-color); |
|
|
cursor: pointer; |
|
|
box-shadow: 0 4px 8px rgba(0, 123, 255, 0.3); |
|
|
margin-top: 15px; |
|
|
transition: all 0.3s ease; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
text-align: center; |
|
|
text-decoration: none; |
|
|
} |
|
|
.submit i { margin-left: 10px; } |
|
|
[dir="rtl"] .submit i { margin-left: 0; margin-right: 10px; } |
|
|
.submit:hover { |
|
|
background-color: var(--primary-hover); |
|
|
transform: translateY(-1px); |
|
|
box-shadow: 0 6px 12px rgba(0, 123, 255, 0.4); |
|
|
} |
|
|
.submit:disabled { background: #555; cursor: not-allowed; box-shadow: none; } |
|
|
|
|
|
#download-btn { |
|
|
background-color: var(--success-color); |
|
|
} |
|
|
#download-btn:hover { |
|
|
background-color: #218838; |
|
|
} |
|
|
|
|
|
.cancel-button { |
|
|
display: block; |
|
|
width: 100%; |
|
|
text-decoration: none; |
|
|
border: 1px solid var(--border-color); |
|
|
outline: none; |
|
|
padding: 14px; |
|
|
border-radius: 8px; |
|
|
color: var(--text-muted); |
|
|
font-size: 1.2em; |
|
|
font-weight: bold; |
|
|
background-color: transparent; |
|
|
cursor: pointer; |
|
|
margin-top: 10px; |
|
|
transition: all 0.3s ease; |
|
|
text-align: center; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
} |
|
|
.cancel-button i { margin-left: 10px; } |
|
|
[dir="rtl"] .cancel-button i { margin-left: 0; margin-right: 10px; } |
|
|
.cancel-button:hover { |
|
|
background-color: var(--border-color); |
|
|
color: var(--text-color); |
|
|
} |
|
|
.cancel-button:disabled { background: #555; cursor: not-allowed; border-color: #555; } |
|
|
.loader-spinner { |
|
|
border: 4px solid #333; |
|
|
border-top: 4px solid var(--primary-color); |
|
|
border-radius: 50%; |
|
|
width: 20px; |
|
|
height: 20px; |
|
|
animation: spin 1s linear infinite; |
|
|
display: none; |
|
|
margin: 15px auto 0; |
|
|
} |
|
|
#result-area { |
|
|
display:none; |
|
|
margin-top: 25px; |
|
|
border-top: 1px solid var(--border-color); |
|
|
padding-top: 25px; |
|
|
text-align: center; |
|
|
} |
|
|
#result-img { |
|
|
max-width: 100%; |
|
|
border-radius: 8px; |
|
|
border: 1px solid var(--border-color); |
|
|
} |
|
|
@keyframes pulse { |
|
|
from { transform: scale(0.9); opacity: 1; } |
|
|
to { transform: scale(1.8); opacity: 0; } |
|
|
} |
|
|
@keyframes spin { |
|
|
to { transform: rotate(360deg); } |
|
|
} |
|
|
@keyframes fadeIn { |
|
|
from { opacity: 0; transform: translateY(10px); } |
|
|
to { opacity: 1; transform: translateY(0); } |
|
|
} |
|
|
#global-toast { |
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
|
width: 320px; |
|
|
max-width: 90%; |
|
|
padding: 15px; |
|
|
display: none; |
|
|
align-items: center; |
|
|
gap: 10px; |
|
|
border-radius: 8px; |
|
|
box-shadow: 0 5px 15px rgba(0,0,0,0.5); |
|
|
position: fixed; |
|
|
bottom: -100px; |
|
|
left: 50%; |
|
|
transform: translateX(-50%); |
|
|
z-index: 2000; |
|
|
transition: opacity 0.3s ease, bottom 0.3s ease; |
|
|
opacity: 0; |
|
|
} |
|
|
#global-toast.show { |
|
|
display: flex; |
|
|
opacity: 1; |
|
|
bottom: 20px; |
|
|
} |
|
|
#global-toast.success { |
|
|
background: #E0F2E9; |
|
|
border: 1px solid var(--success-color); |
|
|
} |
|
|
#global-toast.success .toast-title { color: #155724; } |
|
|
#global-toast.success .toast-icon { fill: var(--success-color); } |
|
|
#global-toast.error { |
|
|
background: #FCE8DB; |
|
|
border: 1px solid var(--error-color); |
|
|
} |
|
|
#global-toast.error .toast-title { color: #71192F; } |
|
|
#global-toast.error .toast-icon { fill: var(--error-color); } |
|
|
.toast-icon { |
|
|
width: 20px; |
|
|
height: 20px; |
|
|
flex-shrink: 0; |
|
|
} |
|
|
.toast-title { |
|
|
font-weight: 600; |
|
|
font-size: 14px; |
|
|
width: 100%; |
|
|
line-height: 1.4; |
|
|
direction: rtl; |
|
|
} |
|
|
.toast-close-btn { |
|
|
background: none; |
|
|
border: none; |
|
|
color: var(--text-muted); |
|
|
cursor: pointer; |
|
|
font-size: 1.5em; |
|
|
line-height: 1; |
|
|
padding: 0 5px; |
|
|
margin-left: auto; |
|
|
flex-shrink: 0; |
|
|
} |
|
|
[dir="rtl"] .toast-close-btn { |
|
|
margin-left: 0; |
|
|
margin-right: auto; |
|
|
} |
|
|
#global-toast.success .toast-close-btn { color: #155724; } |
|
|
#global-toast.error .toast-close-btn { color: #71192F; } |
|
|
|
|
|
|
|
|
|
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
|
|
|
<div id="app-container"> |
|
|
|
|
|
<main> |
|
|
<div class="main-wrapper" id="loginWrapper"> |
|
|
|
|
|
<div class="form"> |
|
|
|
|
|
<p class="title" dir="rtl"> |
|
|
<i class="fas fa-magic" style="margin-left: 10px;"></i> |
|
|
أداة إزالة الخلفية |
|
|
</p> |
|
|
<p class="message-intro"> |
|
|
ارفع صورتك واحصل عليها بخلفية شفافة. (الحد الأقصى: 10 ميجابايت) |
|
|
</p> |
|
|
|
|
|
<input type="file" id="file-input" accept="image/png, image/jpeg" style="display: none;"> |
|
|
|
|
|
<label for="file-input" class="submit" id="upload-label"> |
|
|
<i class="fas fa-upload"></i> اختر صورة |
|
|
</label> |
|
|
|
|
|
<button id="submit-btn" class="cancel-button" style="display: none;"> |
|
|
<i class="fas fa-rocket"></i> ابدأ المعالجة |
|
|
</button> |
|
|
|
|
|
<div class="loader-spinner" id="loadingSpinner"></div> |
|
|
|
|
|
<div id="result-area"> |
|
|
<h3 style="color: var(--text-color);">النتيجة:</h3> |
|
|
<img id="result-img" alt="الصورة بعد إزالة الخلفية"> |
|
|
|
|
|
<a href="#" id="download-btn" class="submit" style="display: none; margin-top: 15px;"> |
|
|
<i class="fas fa-download"></i> تحميل الصورة |
|
|
</a> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
</div> |
|
|
</main> |
|
|
|
|
|
<div id="global-toast"> |
|
|
<svg class="toast-icon" viewBox="0 0 24 24" height="24" width="24" xmlns="http://www.w3.org/2000/svg"> |
|
|
<path d="m13 13h-2v-6h2zm0 4h-2v-2h2zm-1-15c-1.3132 0-2.61358.25866-3.82683.7612-1.21326.50255-2.31565 1.23915-3.24424 2.16773-1.87536 1.87537-2.92893 4.41891-2.92893 7.07107 0 2.6522 1.05357 5.1957 2.92893 7.0711.92859.9286 2.03098 1.6651 3.24424 2.1677 1.21325.5025 2.51363.7612 3.82683.7612 2.6522 0 5.1957-1.0536 7.0711-2.9289 1.8753-1.8754 2.9289-4.4189 2.9289-7.0711 0-1.3132-.2587-2.61358-.7612-3.82683-.5026-1.21326-1.2391-2.31565-2.1677-3.24424-.9286-.92858-2.031-1.66518-3.2443-2.16773-1.2132-.50254-2.5136-.7612-3.8268-.7612z"></path> |
|
|
</svg> |
|
|
<div class="toast-title" id="toast-title"></div> |
|
|
<button class="toast-close-btn" id="toast-close-btn">×</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
const fileInput = document.getElementById('file-input'); |
|
|
const submitBtn = document.getElementById('submit-btn'); |
|
|
const uploadLabel = document.getElementById('upload-label'); |
|
|
const loadingSpinner = document.getElementById('loadingSpinner'); |
|
|
const resultArea = document.getElementById('result-area'); |
|
|
const resultImg = document.getElementById('result-img'); |
|
|
const downloadBtn = document.getElementById('download-btn'); |
|
|
|
|
|
|
|
|
const globalToast = document.getElementById('global-toast'); |
|
|
const toastTitle = document.getElementById('toast-title'); |
|
|
const toastCloseBtn = document.getElementById('toast-close-btn'); |
|
|
let toastTimer; |
|
|
|
|
|
|
|
|
function showToast(message, type = 'success', duration = 5000) { |
|
|
if (toastTimer) clearTimeout(toastTimer); |
|
|
|
|
|
toastTitle.innerHTML = message; |
|
|
globalToast.className = ''; |
|
|
globalToast.classList.add(type); |
|
|
globalToast.classList.add('show'); |
|
|
|
|
|
if (duration > 0) { |
|
|
toastTimer = setTimeout(() => { |
|
|
globalToast.classList.remove('show'); |
|
|
}, duration); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
toastCloseBtn.addEventListener('click', () => { |
|
|
if (toastTimer) clearTimeout(toastTimer); |
|
|
globalToast.classList.remove('show'); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
fileInput.addEventListener('change', () => { |
|
|
globalToast.classList.remove('show'); |
|
|
|
|
|
if (fileInput.files.length > 0) { |
|
|
const file = fileInput.files[0]; |
|
|
const MAX_SIZE = 10 * 1024 * 1024; |
|
|
|
|
|
if (file.size > MAX_SIZE) { |
|
|
showToast('حجم الملف كبير جداً. الحد الأقصى 10 ميجابايت.', 'error', 0); |
|
|
fileInput.value = ''; |
|
|
submitBtn.style.display = 'none'; |
|
|
resultArea.style.display = 'none'; |
|
|
downloadBtn.style.display = 'none'; |
|
|
return; |
|
|
} |
|
|
|
|
|
showToast(`تم اختيار: ${file.name}`, 'success', 3000); |
|
|
submitBtn.style.display = 'flex'; |
|
|
resultArea.style.display = 'none'; |
|
|
downloadBtn.style.display = 'none'; |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
submitBtn.addEventListener('click', async () => { |
|
|
if (fileInput.files.length === 0) return; |
|
|
|
|
|
globalToast.classList.remove('show'); |
|
|
|
|
|
loadingSpinner.style.display = 'block'; |
|
|
submitBtn.disabled = true; |
|
|
uploadLabel.style.pointerEvents = 'none'; |
|
|
uploadLabel.style.opacity = '0.7'; |
|
|
downloadBtn.style.display = 'none'; |
|
|
|
|
|
const formData = new FormData(); |
|
|
const file = fileInput.files[0]; |
|
|
formData.append('file', file); |
|
|
|
|
|
try { |
|
|
const response = await fetch('/remove-bg', { |
|
|
method: 'POST', |
|
|
body: formData |
|
|
}); |
|
|
|
|
|
if (!response.ok) throw new Error('فشل المعالجة'); |
|
|
|
|
|
const imageBlob = await response.blob(); |
|
|
const imageUrl = URL.createObjectURL(imageBlob); |
|
|
|
|
|
resultImg.src = imageUrl; |
|
|
resultArea.style.display = 'block'; |
|
|
|
|
|
const originalFilename = file.name.split('.').slice(0, -1).join('.'); |
|
|
downloadBtn.download = `${originalFilename}-no-bg.png`; |
|
|
downloadBtn.href = imageUrl; |
|
|
downloadBtn.style.display = 'flex'; |
|
|
|
|
|
showToast('اكتملت المعالجة بنجاح!', 'success', 4000); |
|
|
|
|
|
} catch (error) { |
|
|
showToast('⚠️ حدث خطأ. حاول بصورة أخرى أو تأكد من اتصالك.', 'error', 0); |
|
|
downloadBtn.style.display = 'none'; |
|
|
} finally { |
|
|
loadingSpinner.style.display = 'none'; |
|
|
submitBtn.disabled = false; |
|
|
uploadLabel.style.pointerEvents = 'auto'; |
|
|
uploadLabel.style.opacity = '1'; |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
|
|
|
</body> |
|
|
</html> |