/*--------------------  簡単スクロールエリア生成 AS2版 v1.3  2009/08/28 kuboh  v1.3…Macのマウスホイールに対応(2009/10/07)  v1.2…stageの参照方法を変更。クラス内で管理する表示オブジェクト名を変更(2009/08/05)  v1.1…横方向スクロールに対応。スクロールフィールドの解除に対応(2009/08/03) --------------------*/ /*  ・使い方:インスタンス生成時に必要なプロパティをオブジェクトに格納して渡す。  1.ASから設定する場合  var myScroll:EzScrollField = new EzScrollField({body:body, range:range, slider:slider, base:base});  2.ライブラリ内のムービークリップに、リンケージ>クラスから設定する場合  「クラス」に"com.usunekoserv.EzScrollField"を設定。各インスタンス名は予め以下のように設定しておく。  スクロール対象 :_body  マスク :_range  スライダー :_slider  スライダーベース :_base  ※targetPropertyは"_y"固定  ・メソッド  moveBySlider() :現在のスライダの位置を基準に対象を移動させる  moveByBody() :現在の対象の位置を基準にスライダを移動させる  doMove(val:Number) :valピクセル分、スライダを移動させた後、スライダ位置を基準に対象を移動させる  getBodyPos() :現在の対象の位置を0~1の範囲で返す  updateSlider :対象とマスクのサイズから、スライダのサイズを変更する。変更後、対象の位置を基準にスライダを移動させる  removeScrollField(sw:Boolean):対象のスクロール設定を解除。sw に true を渡すと対象のマスクも解除。  ・イベント  onScrollEnable(sw:Boolean) :スライダの有効/無効が切り替わった時に呼ばれる。渡される値はスライダ有効=true, 無効=false。    ・その他:  -bodyの大きさを基準に処理すると不都合があるので、大きさの基準になる表示オブジェクトを別に用意したい。    →インスタンス生成時に引数として useBodyScaleGuide = true, bodyScaleGuide = 基準にしたい表示オブジェクトを渡す  -スクロール操作時に対象に動きにかかるディレイを変更したい    →プロパティ:dilay を変更。デフォルトは0.5秒。  -スライダの最小サイズを設定したい    →プロパティ:minSliderSize を変更。デフォルト値は10px  ・Macのマウスホイールを有効にする為の準備  #swf側の設定  -swfmacmousewheelクラスへパスを通す  #以下html側の設定  -SWFObjectを使用する  -swfmacmousewheel.jsを有効にする  -so.write()を実行した後に var macmousewheel = new SWFMacMouseWheel( so ); を実行する(soはSWFObjectのインスタンス) */ //GREEN SOCKさんのTweenMax(http://blog.greensock.com/tweenmaxas2/)を使用しています。 import gs.TweenMax; import gs.easing.*; //pixelbreakerさんのswfmacmousewheel(http://blog.pixelbreaker.com/flash/swfmacmousewheel/)を使用しています。 import com.pixelbreaker.ui.MouseWheel; //クラス定義 class CC_ezScrollField { /*--------------------  パラメータ --------------------*/ //対象 private var body:MovieClip; //対象マスク private var range:MovieClip; //対象スライダー本体 private var slider:MovieClip; //対象スライダーベース private var base:MovieClip; //対象のサイズ定義用に用意する別の表示オブジェクト private var bodyScaleGuide:MovieClip; //デフォルトの対象名 static var DEFAULT_BODY_NAME:String = "_body"; //デフォルトの対象マスク名 static var DEFAULT_MASK_NAME:String = "_range"; //デフォルトの対象スライダー本体名 static var DEFAULT_SLIDER_NAME:String = "_slider"; //デフォルトの対象スライダーベース名 static var DEFAULT_BASE_NAME:String = "_base"; //デフォルトのサイズ定義用名表示オブジェクト名 static var DEFAULT_BODYSCALE_NAME:String = "_bodyScaleGuide"; //サイズ定義用に用意する別の表示オブジェクトを使用するか public var useBodyScaleGuide:Boolean = false; //スライダを伸縮するか public var elasticSlider:Boolean = true; //マウスホイールは有効か public var isWheelEnable:Boolean = true; //ホイール&ボタンで移動させる移動量にかける倍率 public var scrollRate:Number = 1; //スクロールにディレイをかける時間 public var delay:Number = .5; //スクロール有効? public var isScrollEnable:Boolean; //変化させるプロパティ private var targetProperty:String = "_y"; //直前のスライダー位置 private var lastPos:Number; //最小スライダーサイズ public var minSliderSize:Number = 10; //対象が配置されたドキュメントのstage private var _stage:MovieClip; //マウスホイールのイベントリスナー用オブジェクト private var MHListener:Object; /*--------------------  イベント --------------------*/ //スクロールが有効or無効に切り替わった時に呼ばれる public var onScrollEnable:Function; /*--------------------  コンストラクター --------------------*/ //スクロールエリアのアクティベート // public function CC_ezScrollField(initPrms:Object) { trace("EzScrollFieldを設定"); //初期パラメータの指定がある場合→ASからnewして適用する場合 // if (initPrms != undefined) { //各パラメータを適用 for (var index in initPrms) { trace(" " + index + " = " + initPrms[index]); this[index] = initPrms[index]; } } else { //初期パラメータの指定が無い場合→ライブラリ>リンケージ>クラスから適用する場合 // //デフォルトの名前で適用 body = this[DEFAULT_BODY_NAME]; range = this[DEFAULT_MASK_NAME]; slider = this[DEFAULT_SLIDER_NAME]; base = this[DEFAULT_BASE_NAME]; //対象のサイズ定義用表示オブジェクトが存在すれば定義 if (body[DEFAULT_BODYSCALE_NAME] != undefined) { bodyScaleGuide = body[DEFAULT_BODYSCALE_NAME]; useBodyScaleGuide = true; } } //stageにはbody経由でアクセスしてみる。 _stage = body._parent; trace(" _stage -> " + _stage._name + " / " + typeof _stage ); //マスク適用(すでにマスクされていて、尚かつ未指定もしくは同一オブジェクトならばやらない) if (body._currentMask != range && range != undefined) { body.setMask(range); //マスク適用時にマスク対象のMCにマスクMCの参照を記録しておく body._currentMask = range; } else { trace(" !警告! すでに同内容のマスクが適用されています。mackMC:" + range._name + ", body:" + body._name); } //Macマウスホイール対策 MouseWheel.addListener(this); //各ボタンイベント有効に setEnable(true); //スライダーのアップデート updateSlider(); } /*--------------------  Macマウスホイール用イベント --------------------*/ public function onMouseWheel(delta:Number):Void { if (range.hitTest(_xmouse, _ymouse) || base.hitTest(_xmouse, _ymouse)) { //マウスホイール有効ならdeltaの内容をdoMoveに渡す if (isWheelEnable == true) { doMove( delta ); } } } /*--------------------  ボタンイベントのセット --------------------*/ private function setEnable(sw:Boolean):Void { var classRoot:Object = this; //ドラッグスタート // slider.onPress = function() { //スライダの最大移動範囲 var maxSliderRange:Number; //移動範囲をRectangleオブジェクトに switch (classRoot.targetProperty) { case "_y" : maxSliderRange = classRoot.base._height - classRoot.slider._height; classRoot.slider.startDrag(false, classRoot.base._x, classRoot.base._y, classRoot.base._x, classRoot.base._y + maxSliderRange); break; case "_x" : maxSliderRange = classRoot.base._width - classRoot.slider._width; classRoot.slider.startDrag(false, classRoot.base._x, classRoot.base._y, classRoot.base._x + maxSliderRange, classRoot.base._y); break; } //対象位置のアップデート classRoot.slider.onMouseMove = function () { if (this._visible == false) { return; } //targetPropertyで指定されたプロパティをTweenMaxでトゥイーンさせる。 switch (classRoot.targetProperty) { case "_y" : TweenMax.to(classRoot.body, classRoot.delay, {ease:Strong.easeOut, _y:classRoot.range._y - (classRoot.getScaleMC()._height - classRoot.range._height) * classRoot.getSliderPos()}); break; case "_x" : TweenMax.to(classRoot.body, classRoot.delay, {ease:Strong.easeOut, _x:classRoot.range._x - (classRoot.getScaleMC()._width - classRoot.range._width) * classRoot.getSliderPos()}); break; } } }; //ドラッグストップ // slider.onRelease = slider.onReleaseOutside = function () { this.stopDrag(); } //ベースクリック // base.useHandCursor = false; base.onPress = function () { //スライダの最大移動範囲 var maxSliderRange:Number; //スライダ位置更新 switch (classRoot.targetProperty) { case "_y" : maxSliderRange = this._y + this._height - classRoot.slider._height; classRoot.slider._y = Math.max(this._y, Math.min(maxSliderRange, classRoot.slider._parent._ymouse)); break; case "_x" : maxSliderRange = this._x + this._width - classRoot.slider._width; classRoot.slider._x = Math.max(this._x, Math.min(maxSliderRange, classRoot.slider._parent._xmouse)); break; } classRoot.moveBySlider(); }; //マウスホイール // if (targetProperty == "_y") { //3つのオブジェクト上で有効にしたいので MHListener = new Object(); MHListener.onMouseWheel = function(delta) { if (classRoot.range.hitTest(_xmouse, _ymouse) || classRoot.base.hitTest(_xmouse, _ymouse)) { //マウスホイール有効ならdeltaの内容をdoMoveに渡す if (classRoot.isWheelEnable == true) { classRoot.doMove( delta ); } } }; Mouse.addListener(MHListener); } else if (isWheelEnable == true) { trace(" !警告! マウスホイールは targetProperty が '_y' の場合のみ有効です。"); } } /*--------------------  基準にするサイズ計測用の表示オブジェクト(body or bodyScaleGuide)を返す --------------------*/ public function getScaleMC():MovieClip { //サイズ計測用の表示オブジェクトが存在する&許可している場合 if (useBodyScaleGuide == true && bodyScaleGuide != undefined) { return (bodyScaleGuide); } //しない場合 return (body); } /*--------------------  スライダ位置から対象位置を更新 --------------------*/ public function moveBySlider():Void { //trace("targetProperty = "+targetProperty); if (slider._visible == false) { return; } //targetPropertyで指定されたプロパティをTweenMaxでトゥイーンさせる。 switch (targetProperty) { case "_y" : TweenMax.to(body, delay, {ease:Strong.easeOut, _y:range._y - (getScaleMC()._height - range._height) * getSliderPos()}); break; case "_x" : TweenMax.to(body, delay, {ease:Strong.easeOut, _x:range._x - (getScaleMC()._width - range._width) * getSliderPos()}); break; } } /*--------------------  対象位置からスライダ位置を更新 --------------------*/ public function moveByBody():Void { //trace("targetProperty = "+targetProperty); //スライダの最大移動範囲 var maxSliderRange:Number; //スライダ位置更新 switch (targetProperty) { case "_y" : maxSliderRange = base._y + base._height - slider._height; slider._y = Math.max(base._y, Math.min(maxSliderRange, maxSliderRange * getBodyPos())); break; case "_x" : maxSliderRange = base._x + base._width - slider._width; slider._x = Math.max(base._x, Math.min(maxSliderRange, maxSliderRange * getBodyPos())); break; } //通常の対象更新処理を行ってlastPosを更新 getSliderPos(); //moveBySlider(); } /*--------------------  ボタンやホイールでの操作 --------------------*/ public function doMove(val:Number):Void { //スライダが有効なときのみ有効 if (slider._visible == true) { //スライダの最大移動範囲 var maxSliderRange:Number; //スライダー位置変更 switch (targetProperty) { case "_y" : maxSliderRange = base._y + base._height - slider._height; slider._y = Math.max(base._y, Math.min(maxSliderRange, slider._y - val * scrollRate)); break; case "_x" : maxSliderRange = base._x + base._width - slider._width; slider._x = Math.max(base._x, Math.min(maxSliderRange, slider._x - val * scrollRate)); break; } //対象位置更新 moveBySlider(); } } /*--------------------  スライダの位置を取得(0-1) --------------------*/ public function getSliderPos():Number { var resultPos:Number; switch (targetProperty) { case "_y" : resultPos = (slider._y - base._y) / (base._height - slider._height); break; case "_x" : resultPos = (slider._x - base._x) / (base._width - slider._width); break; } //直前のスライダ位置を記録 lastPos = resultPos; //結果をかえす return resultPos; } /*--------------------  対象の位置を取得(0-1) --------------------*/ public function getBodyPos():Number { var resultPos:Number; switch (targetProperty) { case "_y" : resultPos = -(range._y - body._y) / (range._height - body._height); break; case "_x" : resultPos = -(range._x - body._x) / (range._width - body._width); break; } //直前のスライダ位置を記録 lastPos = resultPos; //結果をかえす return resultPos; } /*--------------------  対象位置からスライダ位置&長さを更新 --------------------*/ public function updateSlider():Void { //スライダ必要? var tmpFlg:Boolean = false; switch (targetProperty) { case "_y" : if (getScaleMC()._height <= range._height) { tmpFlg = true; } break; case "_x" : if (getScaleMC()._width <= range._width) { tmpFlg = true; } break; } //スクロール有効フラグが更新されればイベントを立てる if (isScrollEnable != tmpFlg) { isScrollEnable = tmpFlg; //イベントが設定されていれば実行 if (onScrollEnable != undefined) { onScrollEnable(tmpFlg); } } //スライダ不要ならスライダを消す slider._visible = !tmpFlg; //スライダサイズが可変の場合はサイズ変更 if (elasticSlider == true && slider._visible == true) { switch (targetProperty) { case "_y" : slider._height = Math.max(minSliderSize, base._height * (range._height / getScaleMC()._height)); break; case "_x" : slider._width = Math.max(minSliderSize, base._width * (range._width / getScaleMC()._width)); break; } } //対象がマスクより小さい場合は位置情報をゼロに if (tmpFlg == true) { lastPos = 0; } //スライダの最大移動範囲 var maxSliderRange:Number; //スライダ位置更新 switch (targetProperty) { case "_y" : maxSliderRange = base._height - slider._height; slider._y = base._y + maxSliderRange * lastPos; break; case "_x" : maxSliderRange = base._width - slider._width; slider._x = base._x + maxSliderRange * lastPos; break; } //対象の位置更新 moveByBody(); //ドラッグ中の場合はドラッグ中止 //dragEndHandler(); } /*--------------------  スクロールを解除 --------------------*/ public function removeScrollField(isMaskOff:Boolean):Void { //全てのマウスイベントを解除 trace("EzScrollFieldを解除します。 body:" + body._name + ", targetProperty:" + targetProperty); delete slider.onPress; delete slider.onRelease; delete base.onPress; Mouse.removeListener(MHListener); //isMaskOffがtrueならマスクも解除 if (isMaskOff == true) { trace(" 対象のマスクを解除します。 range:" + range._name); body.setMask(null); } } }