Алгоритм плавной смены фона или изображения
Здравствуйте.
Пытаюсь придумать алгоритм плавной смены фона div-элемента. Есть div-элемент, которому назначается фоновая картинка. По прошествии определенного времени надо сменить фон другой картинкой. Смена фона внешне должна происходить следующим образом: затухание блока (блок становится постепенно черным), далее проявление фона с уже измененным фоном. То есть не просто плавное "опрозрачивание" одного дива, и проявление другого. То что придумал я не работает должным образом: <div id="wrapper"><div id="content"></div></div> Wrapper назначен черный фон, content присваивается конкретная картинка для фона. Соответственно изменяю непрозрачность (opacity) блока content до нуля, изменяю фон content и повышаю непрозрачность до 100. (от 0 до 1 в w3c-совместимых браузерах). За затухание отвечает функция fade, которая в зависимости от флага показано изображение или скрыто повышает или понижает прозрачность блока:
function fade ( el, maxVal, minVal, frames ) {
var vpf = Math.ceil( ( maxVal - minVal ) / frames ); // valuePerFrame
var tpf = Math.ceil( 1000 / el.fps ); // timePerFrame
if ( el._fadeIn ) { // Если объект показан на экране, то надо сделать fadeOut (скрыть)
for ( var i = 1; i <= frames; i++ ) {
(function() {
var opacityValue = maxVal - i * vpf;
var timeInterval = i * tpf;
setTimeout ( function () { setOpacity ( el, opacityValue ); }, timeInterval );
})();}
el._fadeIn = false;
}
else { // Иначе делаем fadeIn, показываем объект
for ( var i = 1; i <= frames; i++ ) {
(function() {
var opacityValue = minVal + i * vpf;
var timeInterval = i * tpf;
setTimeout ( function () { setOpacity ( el, opacityValue ); }, timeInterval );
})();}
el._fadeIn = true;
}
}
Функция, в которой собран механизм содержит в себе нечто вроде:
...
fade ( el, 100, 0, halfFrames );
changeBg(); // изменение фона блока
setTimeout ( function () { fade ( el, 100, 0, halfFrames ); }, el.duration / 2 );
el.currentPos += 1;
...
Если не использовать setTimeout для вывода из черного состояния, то функция fadeIn (2-ая по порядку) перебивает, как я понимаю, первую - fadeOut (1-ая по порядку). Если использовать setTimeout ..., то картинка фона меняется раньше, чем фон затухает. Вопросов несколько: как заставить выполняться нужные мне строки кода по цепочке - до тех пор пока не выполнится предыдущий метод, не запускается следующий? Может стоит как-то изменить способ изменения прозрачности (изменять не циклом for и устанавливая таймауты, но по-другому не представляю, как сделать постепенное изменение) или в принципе нужно использовать другой алгоритм? |
Правильно ли в каждой функции иметь аргумент callback, чтобы вызывать после завершения кода текущей функции?
Что-нибудь вроде:
function fade ( el, maxVal, minVal, frames, callback ) {
...
setTimeout ( function () { setOpacity ( el, opacityValue ); if ( i == frames && callback ) { callback ( el ); } }, timeInterval );
...
}
Как тогда передавать аргументы в функцию callback, если я не знаю, какие аргументы ей понадобятся (в данном случае, я передал "el", но ведь мог послать функцию, которая не знает, что с этим el делать)? Вплане, как сделать вызов функции после выполнения текущей функции более универсальным? |
Цитата:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>12345</title>
<style type="text/css">
#box {
width: 200px;
height: 100px;
opacity: 0;
background-color: #000000;
}
</style>
<script>
inc=0.01
function Go() {
var o=document.getElementById('box')
var val=o.style.opacity
var stop=false
val=+val+inc
switch (val) {
case 0:
stop=true
break
case 1:
inc*=-1
break
default:
}
o.style.opacity=val
if (stop) {
return
}
window.setTimeout(Go,30)
}
</script>
</head>
<body>
<div id='box'></div>
<input type='button' onclick='Go()' value='Go' />
</body>
</html>
Осталось доделать фильтры для ИЕ... Ну и добавить див с картинкой... |
Вариант на заданную тему )))
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
#wrapper {
width: 180px;
height: 180px;
background-color: #000000;
}
#content {
width: 180px;
height: 180px;
background-image: url(http://www.buket.co.ua/planet/srez_cvety/____182.jpg);
}
</style>
</head>
<body>
<div id="wrapper"><div id="content"></div></div>
<script language="JavaScript" type="text/javascript">
function slide(e, b, j, z) {
e = e||document.getElementById(e);
if(e.timer) window.clearTimeout(e.timer)
var a = e.style.cssText;
for (var d in b) {
var g = RegExp("(" + d + ".*?)(\\d+\\.?\\d*)", "i");
g.test(a) ? a = a.replace(g, "$1" + b[d][0]) : d != "opacity" ? a = d + ": " + b[d][0] + "px;" + a : window.ActiveXObject ? a = "filter:progid:DXImageTransform.Microsoft.Alpha(opacity=" + b.opacity[0] + ");" + a : a = "opacity:" + b.opacity[0] / 100 + ";" + a
}
e.style.cssText = a;
var k = (new Date).getTime();
setTimeout(function () {
var h = ((new Date).getTime() - k) / j;
h = h < 0.5 ? Math.pow(2 * h, 3) / 2 : (2 - Math.pow(2 * (1 - h), 3)) / 2;
for (var c in b) {
var i = Math.ceil((b[c][1] - b[c][0]) * h + b[c][0]);
if (c == "opacity" && !window.ActiveXObject) i /= 100;
var f = RegExp("(" + c + ".*?)(\\d+\\.?\\d*)", "i");
a = a.replace(f, "$1" + i)
}
e.style.cssText = a;
if (h < 1) e.timer = setTimeout(arguments.callee, 30);
else {
for (c in b) {
if (c == "opacity" && !window.ActiveXObject) b[c][1] /= 100;
f = RegExp("(" + c + ".*?)(\\d+\\.?\\d*)", "i");
a = a.replace(f, "$1" + b[c][1])
}
e.style.cssText = a;
z&&z()
}
}, 10)
};
var p = {"opacity":[100,0]},
p2 = {"opacity":[0,100]},
content=document.getElementById("content"),
img = ["url(http://img.files.7ja.ru/pics-big/99.jpg)","url(http://www.dostavka-buketov.ru/imag/df156.jpg)","url(http://www.buket.co.ua/planet/srez_cvety/____182.jpg)"]
go=function(){slide(content, p, 4000,function(){content.style.backgroundImage=img[0];img.push(img.shift());slide(content, p2, 3000)})}
</script>
<input type='button' onclick='go()' value='Go' />
</body>
</html>
|
Спасибо за ответы. А по сути, как правильно сделать так, чтобы эффекты, выполнялись последовательно один за другим, даже если откладываешь эффекты с помощью setTimeout?
|
vandy3,
попробуйте заменить конструкцию for для запуска таймаутов на
setTimeout(function() {
/* Тут изменение параметров */
if (/* условие срабатывания итерации */)
setTimeout(arguments.callee, 0);
else callback()
}, 0);
подробнее тут |
kerio.com - тут был такой эффект, не смотрел даже, т.к. такой задачи не было, если не на фреймвоках, то можешь разобрать
|
| Часовой пояс GMT +3, время: 23:14. |