似非iPhone風スクロール
/**
* Copyright sowcodWonderfl ( http://wonderfl.net/user/sowcodWonderfl )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/iRXl
*/
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();
}
}