Translation
by wio_dude
HTML
<div id="tl"></div>
CSS
/* .tl-group:hover {
font-weight: bold;
} */
.tl-group.active-group {
background-color: yellow;
}
.tl-group {
cursor: pointer;
}
/*
.tl-group {
color: red;
} */
JavaScript
const tl = {
src: [
["他", {
group: 0,
sound: [0.05, 0.275],
}],
["很", {
group: 1,
sound: [0.3, 0.68],
}],
["开心", {
group: 2,
sound: [0.68, 1],
}],
["。"]
],
srcAudio: 'https://tatoeba.org/en/audio/download/992961',
dest: [
["He", {
group: 0
}],
[" "],
["is", {
group: 1
}],
[" "],
["happy", {
group: 2
}],
["."]
]
}
function byId(id) {
return document.getElementById(id);
}
$elem = {
src: byId('src'),
dest: byId('dest'),
tl: byId('tl')
};
function create(data) {
const tl = {
data,
$src: document.createElement('div'),
$dest: document.createElement('div'),
activeGroup: null
};
if (data.srcAudio) {
tl.$srcAudio = new Audio(data.srcAudio);
}
console.log(tl)
return tl;
}
function setActiveGroup(tl, group) {
for (const span of tl.$src.querySelectorAll('span')) {
if (span.dataset.group === group) {
span.classList.add('active-group');
} else {
span.classList.remove('active-group');
}
}
for (const span of tl.$dest.querySelectorAll('span')) {
if (span.dataset.group === group) {
span.classList.add('active-group');
} else {
span.classList.remove('active-group');
}
}
}
function removeActiveGroup(tl, group) {
for (const span of tl.$src.querySelectorAll('span')) {
if (span.dataset.group === group) {
span.classList.remove('active-group');
}
}
for (const span of tl.$dest.querySelectorAll('span')) {
if (span.dataset.group === group) {
span.classList.remove('active-group');
}
}
}
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let s = null;
async function playAudioSpan(audio, [spanStart, spanEnd]) {
const start = Math.max(spanStart, 0);
const end = Math.min(spanEnd, audio.duration);
const duration = end - start;
if (!s) {
try {
const response = await...