2009.03.12
category
comments

マウス追従でスクロールするインターフェイス

よく見るインターフェイスで、マウスを動かすだけでスクロールする動きを実装してみた。すごくシンプルに考えてみるとモーション自体のスクリプトはこの3行でいける。

percent = scrollContainer.stage.mouseX / (scrollLength - 1);
pos = (scrollLength - (scrollContainer.width + _space) - _space) * percent;
scrollContainer.x = scrollContainer.x - ((scrollContainer.x - _space - pos) / _friction);

ステージの横幅に対してマウスのx座標が何%の位置にいるのかを割り出して計算させれば意外なほどあっさり実装できる。条件分岐もしなくていいし。クラスにしてみたけど、汎用的に使うにはもうちょいチューニングが必要かも。

ScrollOver.as

package
{
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;

	public class ScrollOver
	{
		private var scrollContainer:DisplayObjectContainer;
		private var scrollLength:uint;
		private var vertical:Boolean;
		private var _space:uint = 0;
		private var _friction:uint = 15;

		public function set space(value:uint):void { _space = value; }
		public function set friction(value:uint):void { _friction = value; }

		//------------------------------
		//   コンストラクタ
		//------------------------------
		public function ScrollOver(mc:DisplayObjectContainer, length:uint, vertical:Boolean = false):void
		{
			scrollContainer = mc;
			scrollLength = length;
			vertical = vertical;
		}

		//------------------------------
		//   スクロールモーション
		//------------------------------
		private function onEnter(e:Event):void
		{
			var percent:Number;
			var pos:Number;

			if (vertical == false && scrollLength < scrollContainer.width)
			{
				percent = scrollContainer.stage.mouseX / (scrollLength - 1);
				pos = (scrollLength - (scrollContainer.width + _space) - _space) * percent;
				scrollContainer.x = scrollContainer.x - ((scrollContainer.x - _space - pos) / _friction);
			}
			else if(vertical == true && scrollLength < scrollContainer.height)
			{
				percent = scrollContainer.stage.mouseY / (scrollLength - 1);
				pos = (scrollLength - (scrollContainer.height + _space) - _space) * percent;
				scrollContainer.y = scrollContainer.y - ((scrollContainer.y - _space - pos) / _friction);
			}
		}

		//------------------------------
		//   スタート
		//------------------------------
		public function start():void
		{
			scrollContainer.addEventListener(Event.ENTER_FRAME, onEnter);
		}

		//------------------------------
		//   ストップ
		//------------------------------
		public function stop():void
		{
			scrollContainer.removeEventListener(Event.ENTER_FRAME, onEnter);
		}

		//------------------------------
		//   ポジションリセット
		//------------------------------
		public function positionReset():void
		{
			scrollContainer.x = _space;
		}
	}
}

ドキュメントクラスはこんな感じ。インスタンス名がboxというmcをステージに配置しておく。boxの中身は写真を横にずらっと配置させる。縦スクロールに対応させるにはnew ScrollOver()の第3引数をtrueにする。frictionは摩擦具合。spaceはスクロールの両サイド間隔。start()メソッドでモーション開始。

Main.as

package
{
	import flash.display.Sprite;
	import flash.display.MovieClip;

	import info.five.ui.ScrollOver;

	public class Main extends Sprite
	{
		public function Main():void
		{
			//-----[横スクロールの場合]
			var so:ScrollOver = new ScrollOver(box, stage.stageWidth);

			//-----[縦スクロールの場合]
			//var so:ScrollOver = new ScrollOver(box, stage.stageHeight, true);
			so.friction = 20;
			so.space = 20;
			so.start();
		}
	}
}

15 Comments

  1. tera Says

    おおぉ~。僕の次のCBCNETコラムのネタも同じようなことを書こうとしているので、前回の地図の件もあわせて運命感じました。

  2. simo Says

    まじですかー。かぶってすいません。汗

    これみたいに、よくあるインターフェイスだけど実装どうやってるの?みたいな解説はすごく勉強になりますのでteraさんの記事を楽しみにしてます!w

    みんなインターフェイスの勉強ってどうやってるんですかね?

  3. おー素晴らしいっすね。
    昔作ったコンテンツでマウスの位置でスクロールするの作ったことありますけど、AS1.0だったこともあってなんかもっと面倒だった気がします。

    ところでインターフェイスとかインタラクションの勉強なんですが、大まじめにやっていきませんか〜?

  4. simo Says

    ぜひぜひやりたいですねー。主催お願いします!w

  5. じゃぁとりあえずは福岡teraco内のネタとしてやってみようかな〜

  6. simo Says

    そうですね。次回のネタとかそのあたりがいいかも。実際のサイトで使われてるエフェクトとかFlash表現を勉強会内で模写とかするのもいいかなと思ってます。みんなでこうやって実装してるんじゃないかと探りながらとかコード書いてみるとか。とりあえず、やってみましょうー。

  7. リンクがくるっと回るScrollover 使い方とずれる原因! jQuery版も

    マウスオーバーでリンクをスクロールさせる事ができるscrollover(JavaScriptモジュール)を試してみました。jQueryプラグイン版もあり、使い方をご紹介します。しかし、クロスブラウザ対応が…

  8. momo Says

    //—–[縦スクロールの場合]
    //var so:ScrollOver = new ScrollOver(box, stage.stageHeight, true);
    こっちに切り替えても縦スクロールにならないんですが、他に変更する部分ってありますか?

    私の設定が悪かったらだけなら聞き流してください。。。

  9. momo Says

    先ほどコメントしたものです。
    private var vertical:Boolean;//ココを
    private var vertical:Boolean = true;//にしたら動きました。

    先ほどのコメントとこのコメントは完全に忘れてくださいませ。
    何でもありません。すみません。。

    そして、いつもBLOG拝読させていただいてます。
    無駄のないサイトデザインで、しかもスクリプトもキレイで、賢いお方だなぁ。っていつも思ってます。
    これからも勉強させていただきます!失礼します!

  10. simo Says

    >momoさん
    はじめましてー。気がついたときにはすでに自己解決されたみたいですね。すいません、返信が遅くて。汗

    間違いや不明点等ありましたらいつでもコメント頂ければと思います。今後ともよろしくお願いしまーす!

  11. Kom Says

    どうも初めまして。
    こちらのActionScriptを参考にFlashを制作させて頂いております(まだ未完成ですが(汗)

    一つ気がついたんですがMacのSafari、Firefoxで見るとFlash部分からマウスを外してFlashより横をクリックしたりウィンドウが非アクティブになると左右どちらかに一気にスクロールして消えたまま戻ってこなくなります。

    ASを見ても原因が分からず・・・。もし分かるようでしたら教えて下さい!

  12. simo Says

    >Komさん
    はじめましてー。おそらくステージから外れた瞬間にmouseXの値がすごい桁数になってませんか?macの挙動はこちらでは確認できませんが、FlashPlayerのバグでそういった症状があるのを見たことがあります。

    こちらのサイトにその解決法が載ってますので確認してみて下さい。
    http://hato-style.chu.jp/note/macmouse.html

  13. Kom Says

    ご回答どうもありがとうございます!
    やはりMac固有のものでしたか・・・。
    参考に挙げて頂いたサイト、拝見して挑戦してみます!

  14. Kom Says

    ご報告です。

    ”ScrollOver.as”の
    if (vertical==false&&scrollLength= 0 && scrollContainer.stage.mouseX < scrollContainer.stage.stageWidth )) return;

    と追記する事でMacでもマウスが外れた場合の処理を行うことができました!

  15. simo Says

    検証ありがとうございます!このスクリプトに限らずMacでのmouseXは気をつけないといけないですねー。勉強になります。

Post a comment




Comment

Trackbacks

この記事のコメント・トラックバックRSS