jquery .animate within Interval (or timeOut) 清除后继续
jquery .animate within Interval (or timeOut) keeps going after clear
我正在学习 JS,正在使用一些代码将音频(口语)与文本(口语的转录)大致同步。
更具体地说,代码逐字符更改文本的背景颜色,相当于播放音频的 ms。此外,您可以单击文本的任何字符以转到音频中的等效毫秒。
我正在使用 Bart Veneman 扳手自动为文本中的每个字符添加跨度,然后 Jquery 使用 for 循环和这些跨度为这些字符的背景颜色设置动画。背景颜色 .animation 每个角色需要 +-240 毫秒。
由于音频 ontimeupdate 似乎不太可靠,我使用一个间隔作为我的计时器:它在音频开始时开始并且 运行s 与它并行。背景颜色.动画发生在此间隔内。
¿有什么问题?:如果您 visit the website(在 Firefox 下工作,而不是 Chrome)并单击文本的任何部分(音频开始播放),然后点击文本的其他部分(音频播放点变化)你会发现一些文本字符的背景颜色仍然存在。这些字符背景颜色未正确清除:
¿我的猜测是什么?:发生这种情况是因为 +-240 毫秒的背景颜色。动画需要发生 VS how/when 我称之为 clearInterval VS how/when 清除背景色的for循环发生了。
更多信息:
清除背景颜色和间隔的 for 循环,两者都 运行 在 audio.onplay.
时触发的函数中
单击文本字符时,音频暂停,播放点更改,并触发 audio.onplay,因此调用该函数。
clearInterval 在 Interval 本身内,如果 audio.onpause 或 on.ended(以及到达文本的最后一个字符)则 运行s。
我已经阅读了 Intervals 循环,没有等待其中的代码块完成,所以我也尝试了超时 here,结果相同。
¿到底发生了什么?
¿解决这个问题的好方法是什么?
谢谢
完整代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es">
<head>
<meta charset="UTF-8">
<title>masculinidades/masculinities TEST 5</title>
</head>
<body>
<audio id="miAudio" preload="auto" controls><source src=audio/talk.mp3 type="audio/mpeg"></audio>
<p id="text">La lógica del empresario criminal, el pensamiento de los
boss coincide con el neoliberalismo más radical. Estar en
situación de decidir sobre la vida y la muerte de todos</p>
<script src="js/spanner.js"></script>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<script>
$(document).ready(function(){
// spanner aplica span .char* en orden creciente al contenido del elemento #text
spanner( document.getElementById("text") );
// guardar el elemento audio y el tamaño del texto en variables
var elAudio = document.getElementById("miAudio");
var durText = $("#text").text().length;
// calcular cada cuantos ms hemos de de avanzar un caracter
var msXchar = Math.floor((elAudio.duration*1000) / durText);
console.log("1 Char cada " + msXchar + " ms");
// al hacer hover en cualquier elemento con clase char(int) colorea y pon cursor
$("[class^='char']").hover(
function() {
$(this).css('cursor', 'e-resize');
if ($(this).css("backgroundColor") != "rgb(0, 250, 154)") {
$(this).css("backgroundColor", "rgb(0, 250, 154)");
} else {
$(this).css("backgroundColor", "rgb(255, 255, 255)");
};
}, function() {
if ($(this).css("backgroundColor") == "rgb(0, 250, 154)") {
$(this).css("backgroundColor", "rgb(255, 255, 255)");
} else {
$(this).css("backgroundColor", "rgb(0, 250, 154)");
};
}
);
/* al hacer click en cualquier elemento con clase char(int) usa (int) para ir al tiempo del audio equivalente */
$("[class^='char']").click(
function() {
elAudio.pause();
console.log("clicked paused")
//extrae el int y escala a tiempo de audio
var thisChar = $(this).attr('class').substring(4);
var thisTime = ((thisChar / durText) * (elAudio.duration));
//muévete a ese tiempo de audio
elAudio.currentTime = thisTime + (msXchar*2/1000)
console.log(thisChar, thisTime);
elAudio.play();
}
);
// cuando se hace play al audio ...
elAudio.onplay = function() {
console.log("onplay");
// + borra todo caracter coloreado
for (var i = 0; i < (durText+1); i++) {
$(".char" + i).css("backgroundColor", "#ffffff")
};
// en qué MILIsegundo del audio estamos y a q equivale en texto?
var actualTime = Math.floor(elAudio.currentTime*1000);
var actualChar = Math.floor(((actualTime/1000) / elAudio.duration) * (durText));
console.log("start " + "ms: " + actualTime , "char: " + actualChar);
// ... inicia un Interval que avanza paralelamente al audio
var elInterval = setInterval(function(){
// colorea el actual char
console.log("start colorea")
$( ".char" + actualChar).animate({
backgroundColor: '#00fa9a'
}, (msXchar*4) );
console.log("end colorea")
// cada loop subir 1 el contador de caracteres, empezando en actualChar
actualChar += 1;
console.log("char actual " + actualChar);
// y subir en msXchar ms el contador de tiempo
actualTime += msXchar;
// si el num de char actual es mayor que el largo total del texto, detenemos el intervalo, lo mismo si se ha pausado o terminado el audio
if (actualChar > (durText)) {clearInterval(elInterval);
console.log("interval cleared actualChar > durText");};
elAudio.onpause = function(){clearInterval(elInterval);
console.log("interval cleared paused");};
elAudio.onended = function(){clearInterval(elInterval);
console.log("interval cleared ended");};
// repite este intervalcada msXchar ms
}, msXchar);
};
});
</script>
</body>
</html>
请注意,animate
方法将异步运行。不同步。
(每个 jQuery.fn.animate
创建其动画计时器。)
因此,您不仅需要清除计时器,还需要清除动画队列。
查看参考资料
.animate(...)
: https://api.jquery.com/animate/
.stop(...)
): https://api.jquery.com/stop/
.finish(...)
: https://api.jquery.com/finish/
演示
我正在学习 JS,正在使用一些代码将音频(口语)与文本(口语的转录)大致同步。
更具体地说,代码逐字符更改文本的背景颜色,相当于播放音频的 ms。此外,您可以单击文本的任何字符以转到音频中的等效毫秒。
我正在使用 Bart Veneman 扳手自动为文本中的每个字符添加跨度,然后 Jquery 使用 for 循环和这些跨度为这些字符的背景颜色设置动画。背景颜色 .animation 每个角色需要 +-240 毫秒。
由于音频 ontimeupdate 似乎不太可靠,我使用一个间隔作为我的计时器:它在音频开始时开始并且 运行s 与它并行。背景颜色.动画发生在此间隔内。
¿有什么问题?:如果您 visit the website(在 Firefox 下工作,而不是 Chrome)并单击文本的任何部分(音频开始播放),然后点击文本的其他部分(音频播放点变化)你会发现一些文本字符的背景颜色仍然存在。这些字符背景颜色未正确清除:
¿我的猜测是什么?:发生这种情况是因为 +-240 毫秒的背景颜色。动画需要发生 VS how/when 我称之为 clearInterval VS how/when 清除背景色的for循环发生了。
更多信息: 清除背景颜色和间隔的 for 循环,两者都 运行 在 audio.onplay.
时触发的函数中单击文本字符时,音频暂停,播放点更改,并触发 audio.onplay,因此调用该函数。
clearInterval 在 Interval 本身内,如果 audio.onpause 或 on.ended(以及到达文本的最后一个字符)则 运行s。
我已经阅读了 Intervals 循环,没有等待其中的代码块完成,所以我也尝试了超时 here,结果相同。
¿到底发生了什么? ¿解决这个问题的好方法是什么?
谢谢
完整代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es">
<head>
<meta charset="UTF-8">
<title>masculinidades/masculinities TEST 5</title>
</head>
<body>
<audio id="miAudio" preload="auto" controls><source src=audio/talk.mp3 type="audio/mpeg"></audio>
<p id="text">La lógica del empresario criminal, el pensamiento de los
boss coincide con el neoliberalismo más radical. Estar en
situación de decidir sobre la vida y la muerte de todos</p>
<script src="js/spanner.js"></script>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<script>
$(document).ready(function(){
// spanner aplica span .char* en orden creciente al contenido del elemento #text
spanner( document.getElementById("text") );
// guardar el elemento audio y el tamaño del texto en variables
var elAudio = document.getElementById("miAudio");
var durText = $("#text").text().length;
// calcular cada cuantos ms hemos de de avanzar un caracter
var msXchar = Math.floor((elAudio.duration*1000) / durText);
console.log("1 Char cada " + msXchar + " ms");
// al hacer hover en cualquier elemento con clase char(int) colorea y pon cursor
$("[class^='char']").hover(
function() {
$(this).css('cursor', 'e-resize');
if ($(this).css("backgroundColor") != "rgb(0, 250, 154)") {
$(this).css("backgroundColor", "rgb(0, 250, 154)");
} else {
$(this).css("backgroundColor", "rgb(255, 255, 255)");
};
}, function() {
if ($(this).css("backgroundColor") == "rgb(0, 250, 154)") {
$(this).css("backgroundColor", "rgb(255, 255, 255)");
} else {
$(this).css("backgroundColor", "rgb(0, 250, 154)");
};
}
);
/* al hacer click en cualquier elemento con clase char(int) usa (int) para ir al tiempo del audio equivalente */
$("[class^='char']").click(
function() {
elAudio.pause();
console.log("clicked paused")
//extrae el int y escala a tiempo de audio
var thisChar = $(this).attr('class').substring(4);
var thisTime = ((thisChar / durText) * (elAudio.duration));
//muévete a ese tiempo de audio
elAudio.currentTime = thisTime + (msXchar*2/1000)
console.log(thisChar, thisTime);
elAudio.play();
}
);
// cuando se hace play al audio ...
elAudio.onplay = function() {
console.log("onplay");
// + borra todo caracter coloreado
for (var i = 0; i < (durText+1); i++) {
$(".char" + i).css("backgroundColor", "#ffffff")
};
// en qué MILIsegundo del audio estamos y a q equivale en texto?
var actualTime = Math.floor(elAudio.currentTime*1000);
var actualChar = Math.floor(((actualTime/1000) / elAudio.duration) * (durText));
console.log("start " + "ms: " + actualTime , "char: " + actualChar);
// ... inicia un Interval que avanza paralelamente al audio
var elInterval = setInterval(function(){
// colorea el actual char
console.log("start colorea")
$( ".char" + actualChar).animate({
backgroundColor: '#00fa9a'
}, (msXchar*4) );
console.log("end colorea")
// cada loop subir 1 el contador de caracteres, empezando en actualChar
actualChar += 1;
console.log("char actual " + actualChar);
// y subir en msXchar ms el contador de tiempo
actualTime += msXchar;
// si el num de char actual es mayor que el largo total del texto, detenemos el intervalo, lo mismo si se ha pausado o terminado el audio
if (actualChar > (durText)) {clearInterval(elInterval);
console.log("interval cleared actualChar > durText");};
elAudio.onpause = function(){clearInterval(elInterval);
console.log("interval cleared paused");};
elAudio.onended = function(){clearInterval(elInterval);
console.log("interval cleared ended");};
// repite este intervalcada msXchar ms
}, msXchar);
};
});
</script>
</body>
</html>
请注意,animate
方法将异步运行。不同步。
(每个 jQuery.fn.animate
创建其动画计时器。)
因此,您不仅需要清除计时器,还需要清除动画队列。
查看参考资料
.animate(...)
: https://api.jquery.com/animate/
.stop(...)
): https://api.jquery.com/stop/
.finish(...)
: https://api.jquery.com/finish/