* アニメーションするドロップダウンメニュー [#vb25e8fc]
** 概要 [#maa86d1f]
- 黄色のヘッダにマウスを合わせると、その下にグレーのメニューがアニメーションしながらドロップダウンする。
- ヘッダからマウスを外すと、グレーのメニューはアニメーションしながら元に戻る。
#ref(menu1.png)
↓
↓
#ref(menu2.png)
↓
↓
#ref(menu3.png)
** 方針 [#z7a7ecde]
- 黄色のヘッダはDTで表す。
- 対応するDDは、子要素としてグレーのメニューを持っており、メニューはULで表す。
- ページロード時点でDDの高さを0にして、結果としてメニューはまったく表示されていない状態にする。
- ヘッダのonmouseoverイベントにハンドラ関数ddmenu()を設定し、slideUp()関数をタイマー設定して、DDの高さを徐々に増やす。
- DDはCSSでoverflow:hiddenしてあるので、DDの高さの領域だけメニューが表示される。
- ヘッダのonmouseoutイベントでは、逆にDDの高さを徐々に減らす事で、状態が元に戻る。
** HTML&JavaScript [#h9199212]
<html>
<head>
<script type="text/javascript">
var SPEED = 15;
var TIMER = 100;
function ddmenu(id, action){
var header = document.getElementById(id + '-header');
var content = document.getElementById(id + '-content');
clearInterval(content.timer); // メニューの上げ下げをクリアする
// メニューを下げる
if (action == 'down') { // すでにメニューが下がりきっていればreturnする
if (content.maxh && content.maxh <= content.offsetHeight) {
return
} else if (!content.maxh) { // 初回はこっちに分岐してくる
content.style.display = 'block';
content.style.height = 'auto'; // CSSのheightを確定させてから、
content.maxh = content.offsetHeight; // DOMのoffsetHeightを取り出して、maxhプロパティにセットし、
content.style.height = '0px'; // heightを再度0にする
}
content.timer = setInterval( function () { slideDown(content) }, TIMER );
// メニューを上げる
} else if (action == 'up') {
content.timer = setInterval( function () { slideUp(content) }, TIMER );
}
}
// メニューを下げる
function slideDown(content){
var currh = content.offsetHeight; // 現在の<dd>の高さを取り出し、
var dist = (Math.round((content.maxh - currh) / SPEED)); // SPEEDを元に何px下げるか決め、
dist = (dist <= 1) ? 1 : dist; // 1px以下の場合は調整した上で、
content.style.height = currh + dist + 'px'; // <dd>の高さをセットする
if (currh > (content.maxh - 2)) { // 十分下がっていればタイマをクリアして終了する
clearInterval(content.timer);
}
}
// メニューを上げる
function slideUp(content){
var currh = content.offsetHeight;
var dist = (Math.round(currh / SPEED));
dist = (dist <= 1) ? 1 : dist;
content.style.height = currh - dist + 'px';
if (currh < 2) {
clearInterval(content.timer);
}
}
// <dt>からonmouseoutしてメニューを上げている最中に<dd>にonmouseoverしたら、
// メニューを下げ直す
function cancel(id){
var header = document.getElementById(id + '-header');
var content = document.getElementById(id + '-content');
clearTimeout(header.timer);
clearInterval(content.timer);
if (content.offsetHeight < content.maxh) {
content.timer = setInterval( function () { slideDown(content) }, TIMER);
}
}
</script>
<style type="text/css">
dt, dd, ul, li {
margin: 0;
padding: 0;
width: 300px;
}
dt { /* <dt>にonmouseoverしてメニューが下がり、*/
background: yellow; /* onmouseoutしてメニューが上がる */
}
dd { /* <dd>がメニューを保持するコンテナ */
display: none; /* ページを開いた時はdisplay:noneして非表示にし、 */
height: 0; /* height:0pxして高さをなくす */
overflow: hidden; /* JSでheightを動的に増加させるが、overflow:hiddenなので、 */
/* <dd>のボックス内の部分しかメニューは表示されない */
position: absolute; /* また、positionとz-indexを指定する事で、 */
z-index: 200; /* <dl>の下にある要素の上にメニューが被さるような表示にする*/
}
ul { /* <ul>がメニュー */
}
li {
background: silver;
border-bottom: 1px solid black;
}
</style>
</head>
<body>
<dl>
<dt id="menu-header" onmouseover="ddmenu('menu','down')" onmouseout="ddmenu('menu', 'up')">dropdown</dt>
<dd id="menu-content" onmouseover="cancel('menu')" onmouseout="ddmenu('menu','up')">
<ul>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</dd>
</dl>
</body>
</html>
** 参考 [#lc27a23e]
http://sandbox.leigeber.com/dropdown/dropdown.html