/* 16.05.2005 */
Плавное открытие/закрытие окна (CSS свойство clip)
Довольно часто на web-страницах возникает потребность в диалоговых окнах. В начале мы используем "родные" javascript-овые Alert, Confirm, Prompt, но желание большего контроля над окном, рождает, со временем, окна на основе слоев. Своё окошко можно "вылизать" по своему усмотрению и показать пользователю во всей красе и не просто показать, а показать красиво - плавно развернуть окно, а затем свернуть.
Текст сообщения для пользователя.
Как плавно развернуть и свернуть окно (слой)?
Для простоты попробуем свернуть/развернуть окно по горизонтали (по вертикали выполняется аналогично).
Первым делом создадим слой:
<style type="text/css">
#dialogWindow {
/* Настраиваем внешний вид слоя */
width: 300px; /* шириша слоя диалогового окна */
height: 200px; /* высота слоя диалогового окна */
background-color: #FFFFCC; /* цвет слоя диалогового окна */
border: 1px dotted gray; /* рамка слоя диалогового окна*/
/* Позиционируем слой по центру */
position: absolute; /* устанавливаем абсолютное позиционирование */
left: 50%; /* устанавливаем верхний левый угол слоя по горизонтали по центру страницы */
top: 50%; /* устанавливаем верхний левый угол слоя по вертикали по центру страницы */
margin-top: -100px; /* сдвигаем слой вверх на половину высоты слоя */
margin-left: -150px; /* сдвигаем слой влево на половину ширины слоя */
/* делаем слой невидимым */
clip: rect(auto 150px auto 150px); /* свойство clip подробно рассмотрим ниже (оно ключевое) */
}
/* заголовок диалогового окна */
.dTitle {
font-weight: bold;
margin: 0;
padding: 5px;
background-color: #CCFFFF;
}
/* текст диалогового окна */
.dBody {
text-align: center;
margin: 0;
padding: 10px 5px;
}
</style>
А сейчас, как я и обещал в комментарии, расмотрим свойство clip, изменение которого и дает нужный нам эффект сворачивания/разворачивания. Данное свойство определяет, так называемую, облать усечения. Что же это такое? Обратимся к
спецификации CSS2,
где сказано: Область усечения определяет, какая часть отображаемого содержимого элемента является видимой. По умолчанию размер и форма области усечения совпадают с размером и формой блока, порожденного элементом. Область усечения может быть изменена при помощи свойства clip
.
Рассмотрим пример: пусть задан параграф P шириной 50px высотой 55px. Изначально область усечения совпадает с размером всего параграфа и параграф виден полностью, но если мы зададим свойству clip параграфа значение
P { clip: rect(15px, 30px, 50px, 10px); }
то получим следующую картину -
где серая область ограниченная сплошной черной линией - это область которую занимает параграф (P's block box), а белый прямоуголиник ограниченный пунктирной линией - это область усечения (clip region) заданая свойством clip. Так вот, в отличии от рисунка, на самом деле, все что не попадает в область усечения обрезается и становиться невидимым. Нажмите сюда чтобы применить свойство clip к нашему изображению и сюда чтобы восстановить исходное состояние.
Cсвойству clip параграфа из примера выше задано значение в форме rect (top right bottom left), где:
- top - величина отступа верхней стороны области вырезки от верхней стороны элемента
- right - величина отступа правой стороны области вырезки от левой стороны элемента
- bottom - величина отступа нижней стороны области вырезки от верхней стороны элемента
- left - величина отступа левой стороны области вырезки от левой стороны элемента
Также top right bottom left вместо длины отступа могут принимать значение auto, которое означает что данная сторона области вырезки совпадает со стороной элемента. т.е. clip: rect (auto auto auto auto); или просто clip: auto; - все стороны области вырезки совпадают со сторонами элемента, и элемент полностью виден.
Обратиться к свойству clip элемента через javascript можно следующим образом:
document.getElementById("elemID").style.clip //Присвоить значение, например так document.getElementById("elemID").style.clip = "rect(15px, 30px, 50px, 10px)"; //или так document.getElementById("elemID").style.clip = "rect(auto, 30px, auto, 10px)"; //сверху не обрезать (top=auto)и снизу не обрезать (bottom=auto), но обрезать по бокам //все что меньше 10px (left) и больше 30px (right)
ВНИМАНИЕ!!! IE, включая версию 7, не понимает присвоения значения auto напрямую:
//показать весь элемент document.getElementById("elemID").style.clip = "auto";
Поэтому для правильной работы во всех браузерах нужно писать:
document.getElementById("elemID").style.clip = "rect(auto, auto, auto, auto)";
Ну, вроде бы разобрались со свойством clip и теперь можем вернуться к нашим диалоговым баранам, в смылле диалоговым окнам. При описании стилей слоя dialogWindow
мы задали
clip: rect(auto 150 auto 150)
. Таким образом мы оставили верх и низ элемента без изменений, а правую и левую стороны обрезали каждую по 150px, что в сумме составляет полную ширину элемента - 300px. Т.е. мы просто скрыли элемент.
Попробуем развернуть скрытое окно по горизонтали. Что для этого нужно? Нужно циклически изменять значения right и left соответственно прибавляя и удаляя некоторое значение от текущих значений до тех пор пока left больше нуля, или right мешьше полной ширины слоя (досточно одного из условий). При этом top и bottom не трогаем, они у нас равны auto. Для получения эффекта постепенного появления или скрытия необходимо изменять clip с временными задержками между итерациями, ибо если их не делать то слой появиться очень быстро, и эффекта разворачивая не будет видно (разве что у вас Intel 386 на 20 MHz на который вы поставили Windows 98 - какой ужас). Заметьте, что подобный процесс сворачивания и разворачивания слоя похож на открытие и закрытие занавеса в театре. Поэтому я в названиях функций использую слово Curtain, что в переводе с англ. - зановес, штора.
var curtainStep = 10; //шаг - количество пикселей на которое будет сворачивать слой за один раз
var curtainTimeout = 15;//задержка перед последующей итерацией для эффекта плавности
//текущее количество обрезаемых пикселей слоя слева и справа
var curtainLeft = 150;
var curtainRight = 150;
var curtainWidth = 300;//ширина слоя
//ф-ция разворачивания слоя
function curtainOpen()
{
if (curtainLeft > 0)//Пока левая граница области усечения не достигла левой границы слоя
{
curtainRight += curtainStep; //раскрываем область усечения справа на curtainStep пикселей
curtainLeft -= curtainStep; //раскрываем область усечения слева на curtainStep пикселей
var rect = 'rect(auto, '+ curtainRight +'px, auto, '+ curtainLeft +'px)';
document.getElementById("dialogWindow").style.clip = rect;
setTimeout(curtainOpen,curtainTimeout); //вызываем эту же функцию повторно через curtainTimeout миллисекунд
}
}
Аналогично пишем функцию сворачивания слоя:
//ф-ция сворачивания слоя
function curtainClose()
{
if (curtainLeft<curtainRight)//Пока левая граница области усечения не встретилась с правой
{
curtainRight -= curtainStep; //сужаем область усечения справа на curtainStep пикселей
curtainLeft += curtainStep; //сужаем область усечения слева на curtainStep пикселей
var rect = 'rect(auto, '+ curtainRight +'px, auto, '+ curtainLeft +'px)';
document.getElementById("dialogWindow").style.clip = rect;
setTimeout(curtainClose,curtainTimeout); //вызываем эту же функцию повторно через curtainTimeout миллисекунд
}
}
Ну, вот и все! Однако на этом можно не останавливаться. Аналогично делается сворачивание по вертикали и одновременно по вертикали и по горизонтали.