In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: 似非iPhone風スクロール

/**
 * Copyright Takayuki.Yamazaki ( http://wonderfl.net/user/Takayuki.Yamazaki )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pBLG
 */

// forked from sowcodWonderfl's 似非iPhone風スクロール
package {
    import flash.display.Sprite;
    import flash.geom.Point;
    [SWF(frameRate=60)]
    public class ScrollTest extends Sprite {
        // iPhoneのスクロールのような動きをさせるテスト。
        // 画面内をドラッグしながらボタンを放すと投げれます。
        //
        // 画面端で跳ね返りすぎるなどするので、iPhoneのものと
        // 同じ動きでは無いです。
        // 画面端でバウンドして画面端で止まるようにするには
        // 加速度を調節してとかいうやり方じゃ出来ないですね。
        
        private var _container:ScrollContainer;
        private var _content:Content;
        
        public function ScrollTest() {
            this._content = new SampleContent();
            
            this._container = new ScrollContainer();
            this._container.content = this._content;
            
            this._container.size = new Point(465,465);
            
            this.addChild(this._container);
        }
    }
}

import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.display.Sprite;
import flash.display.Graphics;

// スクロールコンテナに入れるオブジェクトはこれを実装する。
interface Content {
    function get sprite() : Sprite; // 描画オブジェクトを取得
    function get size() : Point; // サイズを取得
}

// スクロールコンテナの中に入れてるコンテンツ。
class SampleContent extends Sprite implements Content {
    public function SampleContent() {
        this.drawSelf();
    }
    public function get sprite() : Sprite {
        return this;
    }
    public function get size() : Point {
        // コンテンツの大きさ
        return new Point(1200,1200);
    }
    public function drawSelf():void {
        var g:Graphics = this.graphics;
        g.lineStyle(0,0xff0000);
        g.beginFill(0x00aaaa);
        g.moveTo(0,0);
        for(var i:Number = 0; i<100; ++i) {
            g.lineTo(Math.random()*1200,Math.random()*1200);
        }
        g.endFill();
    }
}

// ベースのコンテナ
class AreaContainer extends Sprite {
    private var _content:Content = null;
    private var _size:Point;
    private var _hitArea:Sprite;
    private var _contentSprite:Sprite;
    
    // setter and getter
    public function set content(value:Content):void {
        if(this._content != null) this._contentSprite.removeChild(this._content.sprite);
        this._content = value;
        this._contentSprite.addChild(this._content.sprite);
    }
    public function get content():Content { return this._content; }
    
    public function set size(value:Point):void {
        // サイズに合わせてクリック可能領域も調整
        this._size = value;
        this._hitArea.width = value.x;
        this._hitArea.height = value.y;
    }
    public function get size():Point { return this._size; }
    
    // constructor
    public function AreaContainer() {
        // クリック可能領域作成
        this._hitArea = createHitArea();
        this.addChild(this._hitArea);
        this.hitArea = this._hitArea;
        
        this._contentSprite = new Sprite();
        this.addChild(this._contentSprite);
    }
    
    private function createHitArea():Sprite {
        var sp:Sprite = new Sprite();
        sp.visible = false;
        var hitg:Graphics = sp.graphics;
        hitg.beginFill(0x000000);
        hitg.drawRect(0,0,100,100);
        hitg.endFill();
        return sp;
    }
}

// スクロール機能付きコンテナ
class ScrollContainer extends AreaContainer {
    private var _firstP:Point; // クリックした時点のマウス座標
    private var _beforeP:Point; // 前フレームのマウス座標
    private var _baseP:Point; // クリックした時点でのコンテンツの座標
    private var _beforeContentP:Point; // 前フレームのコンテンツの座標
    private var _velocity:Point; // 移動速度
    private var _isMouseDown:Boolean;
    private var _hScrollBar:ScrollBar;
    private var _vScrollBar:ScrollBar;
    
    override public function set size(value:Point):void {
        super.size = value;
        this._vScrollBar.height = value.y * value.y / this.content.size.y;
        this._hScrollBar.width = value.x * value.x / this.content.size.x;
        this._vScrollBar.x = this.size.x - this._vScrollBar.width;
        this._hScrollBar.y = this.size.y - this._hScrollBar.height;
    }
    
    public function ScrollContainer() {
        this._vScrollBar = new ScrollBar();
        this._vScrollBar.width = 10;
        this.addChild(this._vScrollBar);
        this._hScrollBar = new ScrollBar();
        this._hScrollBar.height = 10;
        this.addChild(this._hScrollBar);
        
                this._vScrollBar.visible = this._hScrollBar.visible = false;
        
        // イベント登録
        this.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
        this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
        this.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
    }
    
    private function onMouseDown(ev:MouseEvent):void {
        this._isMouseDown = true;
        this._beforeP = new Point(this.mouseX, this.mouseY);
        this._firstP = this._beforeP.clone();
        this._baseP = new Point(this.content.sprite.x, this.content.sprite.y);
        this._beforeContentP = this._baseP.clone();
        
                this._vScrollBar.visible = this._hScrollBar.visible = true;
    }
    
    private function onEnterFrame(ev:Event):void {
        var maxP:Point = content.size.subtract(this.size); // 最大スクロール値
        var newContentP:Point;
        if(this._isMouseDown) {
            // ドラッグ中
            var newP:Point = new Point(this.mouseX, this.mouseY);
            var diffP:Point = newP.subtract(this._firstP);
            newContentP = this._baseP.add(diffP);
            
            // 端オーバー時の処理
            if(newContentP.x > 0) newContentP.x = newContentP.x / 2;
            if(newContentP.y > 0) newContentP.y = newContentP.y / 2;
            if(newContentP.x < -maxP.x)
                newContentP.x = (maxP.x + newContentP.x) / 2 + -maxP.x;
            if(newContentP.y < -maxP.y)
                newContentP.y = (maxP.y + newContentP.y) / 2 + -maxP.y;
            
            // 座標の適用
            this.content.sprite.x = newContentP.x;
            this.content.sprite.y = newContentP.y;
            
            this._velocity = newContentP.subtract(this._beforeContentP);
        } else {
            if(this._beforeContentP.x > 0) 
                this._velocity.x = this._velocity.x * 0.9 - this._beforeContentP.x * 0.05;
            if(this._beforeContentP.y > 0) 
                this._velocity.y = this._velocity.y * 0.9 - this._beforeContentP.y * 0.05;
            if(this._beforeContentP.x < -maxP.x)
                this._velocity.x = this._velocity.x * 0.9 - (maxP.x + this._beforeContentP.x) * 0.05;
            if(this._beforeContentP.y < -maxP.y)
                this._velocity.y = this._velocity.y * 0.9 - (maxP.y + this._beforeContentP.y) * 0.05;
                
            newContentP = (new Point(this.content.sprite.x, this.content.sprite.y)).add(this._velocity);
            
            this._velocity = new Point(this._velocity.x * 0.95, this._velocity.y * 0.95);
            if(this._velocity.length < 0.1) {
                this._velocity = new Point();
                this._vScrollBar.visible = this._hScrollBar.visible = false;
            }
            this.content.sprite.x += this._velocity.x;
            this.content.sprite.y += this._velocity.y;
        }
        
        // スクロールバー
        this._vScrollBar.y = - this.size.y * this.content.sprite.y / this.content.size.y;
        this._hScrollBar.x = - this.size.x * this.content.sprite.x / this.content.size.x;
        
        this._beforeContentP = newContentP;
        this._beforeP = newP;
    }
    
    private function onMouseUp(ev:MouseEvent):void {
        this._isMouseDown = false;
    }
}

class ScrollBar extends Sprite {
    public function ScrollBar() {
        this.drawSelf();
    }
    private function drawSelf() : void {
        var g:Graphics = this.graphics;
        g.beginFill(0x808080,0.5);
        g.drawRect(0,0,50,50);
        g.endFill();
    }
}