Added audio pronunciation for all Arabic letters and harakaat
This commit is contained in:
parent
0589b33a25
commit
7819a7f097
101
index.html
101
index.html
@ -227,6 +227,22 @@ body {
|
|||||||
direction: ltr; text-align: center; font-family: 'Inter', sans-serif;
|
direction: ltr; text-align: center; font-family: 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audio-btn-sm {
|
||||||
|
width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border);
|
||||||
|
background: var(--bg-card); cursor: pointer; display: inline-flex; align-items: center;
|
||||||
|
justify-content: center; font-size: 16px; transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.audio-btn-sm:hover { background: var(--quran-gold); border-color: var(--quran-gold); color: #fff; transform: scale(1.1); }
|
||||||
|
|
||||||
|
.learn-btn {
|
||||||
|
padding: 8px 16px; border-radius: 8px; border: 1px solid var(--border);
|
||||||
|
background: var(--bg-card); cursor: pointer; font-size: 12px; font-weight: 600;
|
||||||
|
color: var(--text-secondary); transition: all 0.2s; margin-left: auto; white-space: nowrap;
|
||||||
|
}
|
||||||
|
.learn-btn:hover { background: var(--quran-green); border-color: var(--quran-green); color: #fff; }
|
||||||
|
|
||||||
|
.letter-card:hover .letter-big { color: var(--quran-gold); }
|
||||||
|
|
||||||
.ayat-example {
|
.ayat-example {
|
||||||
background: var(--bg); border-radius: 16px; padding: 32px;
|
background: var(--bg); border-radius: 16px; padding: 32px;
|
||||||
border: 2px solid var(--quran-gold); margin: 24px 0; text-align: center;
|
border: 2px solid var(--quran-gold); margin: 24px 0; text-align: center;
|
||||||
@ -682,6 +698,10 @@ body {
|
|||||||
<section class="section" style="padding-top:120px">
|
<section class="section" style="padding-top:120px">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section-header"><div class="badge">ШАГ 1</div><h2>Арабский алфавит</h2><p>28 букв — основа чтения Корана</p></div>
|
<div class="section-header"><div class="badge">ШАГ 1</div><h2>Арабский алфавит</h2><p>28 букв — основа чтения Корана</p></div>
|
||||||
|
<div style="text-align:center;margin-bottom:24px">
|
||||||
|
<button class="btn btn-primary" onclick="playAllLetters()">🔊 Прослушать все буквы</button>
|
||||||
|
<p style="font-size:13px;color:var(--text-secondary);margin-top:8px">Нажмите на букву или 🔊 чтобы услышать произношение</p>
|
||||||
|
</div>
|
||||||
<div id="alphabetGrid"></div>
|
<div id="alphabetGrid"></div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -1218,10 +1238,13 @@ function renderAlphabet() {
|
|||||||
const grid = document.getElementById('alphabetGrid');
|
const grid = document.getElementById('alphabetGrid');
|
||||||
const p = getProgress();
|
const p = getProgress();
|
||||||
grid.innerHTML = alphabetData.map((l, i) => `
|
grid.innerHTML = alphabetData.map((l, i) => `
|
||||||
<div class="letter-card" onclick="learnLetter(${i})">
|
<div class="letter-card">
|
||||||
<div class="letter-big">${l.letter}</div>
|
<div class="letter-big" onclick="speakLetter(${i})" style="cursor:pointer" title="Нажмите чтобы услышать">${l.letter}</div>
|
||||||
<div class="letter-info">
|
<div class="letter-info">
|
||||||
<div class="name">${l.name}</div>
|
<div style="display:flex;align-items:center;gap:12px;margin-bottom:4px">
|
||||||
|
<div class="name">${l.name}</div>
|
||||||
|
<button class="audio-btn-sm" onclick="event.stopPropagation();speakLetter(${i})" title="Прослушать">🔊</button>
|
||||||
|
</div>
|
||||||
<div class="transcription">[${l.transcription}]</div>
|
<div class="transcription">[${l.transcription}]</div>
|
||||||
<div class="description">${l.description}</div>
|
<div class="description">${l.description}</div>
|
||||||
<div class="letter-positions">
|
<div class="letter-positions">
|
||||||
@ -1230,10 +1253,65 @@ function renderAlphabet() {
|
|||||||
<div class="letter-position">${l.positions.final}<small>конец</small></div>
|
<div class="letter-position">${l.positions.final}<small>конец</small></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="learn-btn" onclick="event.stopPropagation();learnLetter(${i})">✓ Изучено</button>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function speakLetter(idx) {
|
||||||
|
const letter = alphabetData[idx].letter;
|
||||||
|
if ('speechSynthesis' in window) {
|
||||||
|
window.speechSynthesis.cancel();
|
||||||
|
const utterance = new SpeechSynthesisUtterance(letter);
|
||||||
|
utterance.lang = 'ar-SA';
|
||||||
|
utterance.rate = 0.5;
|
||||||
|
utterance.pitch = 1;
|
||||||
|
window.speechSynthesis.speak(utterance);
|
||||||
|
}
|
||||||
|
showToast('Произношение: ' + alphabetData[idx].name, 'info');
|
||||||
|
}
|
||||||
|
|
||||||
|
function playAllLetters() {
|
||||||
|
if (!('speechSynthesis' in window)) {
|
||||||
|
showToast('Ваш браузер не поддерживает аудио', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.speechSynthesis.cancel();
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
function speakNext() {
|
||||||
|
if (index < alphabetData.length) {
|
||||||
|
const utterance = new SpeechSynthesisUtterance(alphabetData[index].letter);
|
||||||
|
utterance.lang = 'ar-SA';
|
||||||
|
utterance.rate = 0.5;
|
||||||
|
utterance.pitch = 1;
|
||||||
|
|
||||||
|
// Highlight current letter
|
||||||
|
const cards = document.querySelectorAll('.letter-card');
|
||||||
|
cards.forEach(c => c.style.borderColor = 'var(--border)');
|
||||||
|
if (cards[index]) {
|
||||||
|
cards[index].style.borderColor = 'var(--quran-gold)';
|
||||||
|
cards[index].scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
|
||||||
|
utterance.onend = () => {
|
||||||
|
index++;
|
||||||
|
setTimeout(speakNext, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.speechSynthesis.speak(utterance);
|
||||||
|
showToast('Буква ' + alphabetData[index].name + ' (' + (index + 1) + '/28)', 'info');
|
||||||
|
} else {
|
||||||
|
showToast('Все буквы прослушаны!', 'success');
|
||||||
|
const cards = document.querySelectorAll('.letter-card');
|
||||||
|
cards.forEach(c => c.style.borderColor = 'var(--border)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
speakNext();
|
||||||
|
}
|
||||||
|
|
||||||
function learnLetter(idx) {
|
function learnLetter(idx) {
|
||||||
const p = getProgress();
|
const p = getProgress();
|
||||||
const key = 'letter-' + idx;
|
const key = 'letter-' + idx;
|
||||||
@ -1245,8 +1323,10 @@ function learnLetter(idx) {
|
|||||||
saveProgress(p);
|
saveProgress(p);
|
||||||
showToast('Буква ' + alphabetData[idx].name + ' изучена!', 'success');
|
showToast('Буква ' + alphabetData[idx].name + ' изучена!', 'success');
|
||||||
checkAchievements();
|
checkAchievements();
|
||||||
|
} else {
|
||||||
|
showToast('Буква ' + alphabetData[idx].name + ' уже изучена', 'info');
|
||||||
}
|
}
|
||||||
speak(alphabetData[idx].letter);
|
speakLetter(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderHarakaat() {
|
function renderHarakaat() {
|
||||||
@ -1262,6 +1342,7 @@ function renderHarakaat() {
|
|||||||
<div style="font-size:13px;color:var(--text-secondary);margin-top:4px">${h.description}</div>
|
<div style="font-size:13px;color:var(--text-secondary);margin-top:4px">${h.description}</div>
|
||||||
<div class="example">${h.example}</div>
|
<div class="example">${h.example}</div>
|
||||||
<div style="font-size:12px;color:var(--text-secondary)">${h.exampleWord}</div>
|
<div style="font-size:12px;color:var(--text-secondary)">${h.exampleWord}</div>
|
||||||
|
<button class="audio-btn-sm" style="margin-top:12px" onclick="event.stopPropagation();speakHaraka('${h.example}','${h.name}')">🔊 Прослушать</button>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|
||||||
@ -1273,10 +1354,22 @@ function renderHarakaat() {
|
|||||||
<div style="font-size:13px;color:var(--text-secondary);margin-top:4px">${h.description}</div>
|
<div style="font-size:13px;color:var(--text-secondary);margin-top:4px">${h.description}</div>
|
||||||
<div class="example">${h.example}</div>
|
<div class="example">${h.example}</div>
|
||||||
<div style="font-size:12px;color:var(--text-secondary)">${h.exampleWord}</div>
|
<div style="font-size:12px;color:var(--text-secondary)">${h.exampleWord}</div>
|
||||||
|
<button class="audio-btn-sm" style="margin-top:12px" onclick="event.stopPropagation();speakHaraka('${h.example}','${h.name}')">🔊 Прослушать</button>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function speakHaraka(text, name) {
|
||||||
|
if ('speechSynthesis' in window) {
|
||||||
|
window.speechSynthesis.cancel();
|
||||||
|
const utterance = new SpeechSynthesisUtterance(text);
|
||||||
|
utterance.lang = 'ar-SA';
|
||||||
|
utterance.rate = 0.5;
|
||||||
|
window.speechSynthesis.speak(utterance);
|
||||||
|
}
|
||||||
|
showToast('Произношение: ' + name, 'info');
|
||||||
|
}
|
||||||
|
|
||||||
function learnHaraka(idx) {
|
function learnHaraka(idx) {
|
||||||
const p = getProgress();
|
const p = getProgress();
|
||||||
const key = 'haraka-' + idx;
|
const key = 'haraka-' + idx;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user