ゆっくり開閉するプルダウンメニューに関する解説サイトを教えてください。
「prototype」や「script.aculo.us」を組み合わせて、なんとか実現できそうな所までは分かったのですが、何故かうまく稼動しなくて困っております。
なお、メニューはOnClickではなく、OnMouseやOutMouseでイベント判定をし、プルダウンするメニューを作りたいと考えております。
どなたかお心当たりの方がいらっしゃいましたら、よろしくお願い致します。
スムーズに開閉するタイプのサンプルページです。
ソースもダウンロードできますよ。
解説サイトは分からないのですが、参考までに。
私もやってみましたが、script.aculo.usのEffect.BlindUp/Effect.BlindDownはこの件に向いていない気がします。アニメーション途中に更にイベントが発生することは想定していないような。。。
onmouseover、onmouseoutで動作させる場合、メニューのタイトル(最初から見えている部分)と、メニューの内容部分(スクロールする部分)を同一要素に入れ、その親要素のイベントを設定するのがやりやすいと思います。(別にするとタイトル部分からないよう部分へマウスカーソルを動かす度にイベントが発生する)
以下は私が自作したものです。prototype.jsは使用してます。親要素にタイトル、内容の要素をその順番で記述してください(直の子要素は2つだけになります)。その親要素を第一引数にして(ID、要素指定どちらでも可)scrollMenuクラスのインスタンスを作成してください。第二引数で0.01秒ごとにスクロールするpx値を指定できます。無指定時はデフォルトで2になります。
<html> <head> <title></title> <style> <!-- a{ color:red; } #menu1{ float:left; } .title{ border:solid blue 2px; width:100px; } --> </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> <!-- //scrollMenuクラス var scrollMenu = Class.create(); scrollMenu.prototype = { initialize: function(obj, speed){ this.obj = $(obj); this.speed = speed || 2; Element.cleanWhitespace(this.obj); this.title = this.obj.childNodes[0]; this.menu = this.obj.childNodes[1]; Element.setStyle(this.menu, { visibility:'hidden', position:'absolute', overflow:'hidden', display:'block' }); var bkp = Element.getStyle(this.menu, 'height'); Element.setStyle(this.menu, {height:''}); this.height = Element.getHeight(this.menu); var value = Position.cumulativeOffset(this.title); var left = value[0]; var top = value[1] + Element.getHeight(this.title); Element.setStyle(this.menu, { height:'1px', left:left, top:top }); Event.observe(this.obj, 'mouseover', this.start.bind(this), false); Event.observe(this.obj, 'mouseout', this.stop.bind(this), false); }, start: function(){ Element.setStyle(this.menu, { visibility:'visible' }); if(this.tid) clearTimeout(this.tid); this.tid = setInterval(this.show.bind(this), 10); }, show: function(){ var height = parseInt(Element.getStyle(this.menu, 'height')); height += this.speed; if(height >= this.height){ height = this.height; clearTimeout(this.tid); } Element.setStyle(this.menu, {height:height + 'px'}); }, stop: function(){ if(this.tid) clearTimeout(this.tid); this.tid = setInterval(this.hide.bind(this), 10); }, hide: function(){ var height = parseInt(Element.getStyle(this.menu, 'height')); height -= this.speed; if(height <= 1){ height = 1; Element.setStyle(this.menu, { visibility:'hidden' }); clearTimeout(this.tid); } Element.setStyle(this.menu, {height:height + 'px'}); } } //onloadイベントでインスタンス作成 Event.observe(window, 'load', function(){ new scrollMenu('menu1'); new scrollMenu('menu2'); }, false); //--> </script> </head> <body> <div id="menu1"> <div class="title">MENU 1</div> <div> ┣ <a href="リンク先URL">MENU1-1</a><BR> ┣ <a href="リンク先URL">MENU1-2</a><BR> ┗ <a href="リンク先URL">MENU1-3</a><BR> </div> </div> <div id="menu2"> <div class="title">MENU 2</div> <div> ┣ <a href="リンク先URL">MENU2-1</a><BR> ┣ <a href="リンク先URL">MENU2-2</a><BR> ┗ <a href="リンク先URL">MENU2-3</a><BR> </div> </div> </body> </html>
参考になりますでしょうか。
ダミーURL:http://q.hatena.ne.jp/
コメントしたとおり、2の回答だとレイアウトが崩れる場合があります。改善したものを提示します。注意として、メニュータイトルと内容の幅をスタイル指定するようにしてください(下ではtitleクラスとcontentsクラスのwidth)。
バタバタしてしまってすみません・・・。
<html> <head> <title></title> <style> <!-- a{ color:red; } .menu{ float:left; } .title{ border:solid blue 2px; width:100px; } .contents{ width:100px; } --> </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> <!-- //scrollMenuクラス var scrollMenu = Class.create(); scrollMenu.prototype = { initialize: function(obj, speed){ this.obj = $(obj); this.speed = speed || 2; Element.cleanWhitespace(this.obj); this.title = this.obj.childNodes[0]; this.menu = this.obj.childNodes[1]; Element.setStyle(this.menu, { visibility:'hidden', position:'absolute', overflow:'hidden', display:'block', height:'1px' }); Event.observe(this.obj, 'mouseover', this.start.bind(this), false); Event.observe(this.obj, 'mouseout', this.stop.bind(this), false); }, start: function(){ var bkp = Element.getStyle(this.menu, 'height'); Element.setStyle(this.menu, {height:''}); this.height = Element.getHeight(this.menu); var value = Position.cumulativeOffset(this.title); var left = value[0]; var top = value[1] + Element.getHeight(this.title); Element.setStyle(this.menu, { left:left, top:top, visibility:'visible', height:bkp }); if(this.tid) clearTimeout(this.tid); this.tid = setInterval(this.show.bind(this), 10); }, show: function(){ var height = parseInt(Element.getStyle(this.menu, 'height')); height += this.speed; if(height >= this.height){ height = this.height; clearTimeout(this.tid); } Element.setStyle(this.menu, {height:height + 'px'}); }, stop: function(){ if(this.tid) clearTimeout(this.tid); this.tid = setInterval(this.hide.bind(this), 10); }, hide: function(){ var height = parseInt(Element.getStyle(this.menu, 'height')); height -= this.speed; if(height <= 1){ height = 1; Element.setStyle(this.menu, { visibility:'hidden' }); clearTimeout(this.tid); } Element.setStyle(this.menu, {height:height + 'px'}); } } //onloadイベントでインスタンス作成 Event.observe(window, 'load', function(){ new scrollMenu('menu1'); new scrollMenu('menu2'); new scrollMenu('menu3'); }, false); //--> </script> </head> <body> <div id="menu1" class="menu"> <div class="title">MENU 1</div> <div class="contents"> ┣ <a href="リンク先URL">MENU1-1</a><BR> ┣ <a href="リンク先URL">MENU1-2</a><BR> ┗ <a href="リンク先URL">MENU1-3</a><BR> </div> </div> <div id="menu2" class="menu"> <div class="title">MENU 2</div> <div class="contents"> ┣ <a href="リンク先URL">MENU2-1</a><BR> ┣ <a href="リンク先URL">MENU2-2</a><BR> ┗ <a href="リンク先URL">MENU2-3</a><BR> </div> </div> <div id="menu3" class="menu"> <div class="title">MENU 3</div> <div class="contents"> ┣ <a href="リンク先URL">MENU3-1</a><BR> ┣ <a href="リンク先URL">MENU3-2</a><BR> ┗ <a href="リンク先URL">MENU3-3</a><BR> </div> </div> </body> </html>
ダミーURL:http://q.hatena.ne.jp/
コメント(2件)
何パターンか試してみたのですが、おっしゃるとおりscript.aculo.usのEffect.BlindUp/Effect.BlindDownでは実現することができそうにありませんでした。
足元、mootoolsを利用したりしながら組んでおりました。
ご回答いただいた内容を参考にしつつ、メニューを作成してみたいと思います。
どうもありがとうございました。