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

アニメーションするドロップダウンメニュー

概要

  • 黄色のヘッダにマウスを合わせると、その下にグレーのメニューがアニメーションしながらドロップダウンする。
  • ヘッダからマウスを外すと、グレーのメニューはアニメーションしながら元に戻る。
menu1.png

 ↓

menu2.png

 ↓

menu3.png

方針

  • 黄色のヘッダはDTで表す。
  • 対応するDDは、子要素としてグレーのメニューを持っており、メニューはULで表す。
  • ページロード時点でDDの高さを0にして、結果としてメニューはまったく表示されていない状態にする。
  • ヘッダのonmouseoverイベントにハンドラ関数ddmenu()を設定し、slideUp()関数をタイマー設定して、DDの高さを徐々に増やす。
  • DDはCSSでoverflow:hiddenしてあるので、DDの高さの領域だけメニューが表示される。
  • ヘッダのonmouseoutイベントでは、逆にDDの高さを徐々に減らす事で、状態が元に戻る。

HTML&JavaScript

<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>

参考

http://sandbox.leigeber.com/dropdown/dropdown.html


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

Last-modified: 2010-05-10 (月) 02:36:07 (2755d)