* アニメーションするドロップダウンメニュー [#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

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS