UI like Flash CS5
UI like as Flash Professional CS5
* Flash CS5風なインターフェース
* ドラッグできる数値入力の汎用コンポーネントを作ってみた
*
* @author yasu
* @see http://clockmaker.jp/
/**
* Copyright clockmaker ( http://wonderfl.net/user/clockmaker )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/aSwW
*/
/**
* UI like as Flash Professional CS5
* Flash CS5風なインターフェース
* ドラッグできる数値入力の汎用コンポーネントを作ってみた
*
* @author yasu
* @see http://clockmaker.jp/
*/
package
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;
/**
* UI like as Flash Professional CS5
* @author yasu
*/
[SWF(width=465, height=465, frameRate=60)]
public class Main extends Sprite
{
public function Main()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
var bmd:BitmapData = new BitmapData(4, 4, false, 0xFF99CC00);
bmd.setPixel(1, 1, 0x6633FF);
bmd.setPixel(3, 3, 0x6633FF);
var bg:Shape = new Shape();
bg.graphics.beginBitmapFill(bmd);
bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
addChild(bg);
_ball = new Shape();
_ball.graphics.beginFill(0x0);
_ball.graphics.drawCircle(0, 0, stage.width / 2 - 100);
addChild(_ball);
_dummyBall = new Sprite();
_dummyBall.graphics.beginFill(0x0, 0);
_dummyBall.graphics.drawCircle(0, 0, 100);
_dummyBall.addEventListener(MouseEvent.MOUSE_DOWN, _onBallMouseDown);
addChild(_dummyBall);
bg.mask = _ball;
_ball.x = _dummyBall.x = stage.stageWidth / 4;
_ball.y = _dummyBall.y = stage.stageHeight / 4;
_ui = new Sprite();
_ui.x = stage.stageWidth - 353 - 20;
_ui.y = (stage.stageHeight - 184) / 2 >> 0;
addChild(_ui);
var loader:Loader = new Loader();
loader.load(new URLRequest("http://assets.wonderfl.net/images/related_images/6/6f/6f93/6f93bdd5ba508b74fdb3b16e88ead265608729a8"), new LoaderContext(true));
_ui.addChild(loader);
var header:Sprite = new Sprite();
header.graphics.beginFill(0x0, 0);
header.graphics.drawRect(0, 0, 353, 30);
header.addEventListener(MouseEvent.MOUSE_DOWN, _onHeaderMouseDown);
_ui.addChild(header);
_sliderX = new DraggableTextInput();
_sliderX.x = 75;
_sliderX.y = 118;
_sliderX.minimum = -5760;
_sliderX.maximum = 5760;
_sliderX.value = _ball.x;
_sliderX.addEventListener(Event.CHANGE, _onChange);
_ui.addChild(_sliderX);
_sliderY = new DraggableTextInput();
_sliderY.x = 174;
_sliderY.y = 118;
_sliderY.minimum = -5760;
_sliderY.maximum = 5760;
_sliderY.value = _ball.y;
_sliderY.addEventListener(Event.CHANGE, _onChange);
_ui.addChild(_sliderY);
_sliderW = new DraggableTextInput();
_sliderW.x = 75;
_sliderW.y = 150;
_sliderW.minimum = 1;
_sliderW.maximum = 5760;
_sliderW.value = _ball.width;
_sliderW.snapInterval = 1;
_sliderW.addEventListener(Event.CHANGE, _onChange);
_ui.addChild(_sliderW);
_sliderH = new DraggableTextInput();
_sliderH.x = 174;
_sliderH.y = 150;
_sliderH.minimum = 1;
_sliderH.maximum = 5760;
_sliderH.value = _ball.height;
_sliderH.snapInterval = 1;
_sliderH.addEventListener(Event.CHANGE, _onChange);
_ui.addChild(_sliderH);
}
private var _ui:Sprite;
private var _sliderX:DraggableTextInput;
private var _sliderY:DraggableTextInput;
private var _sliderW:DraggableTextInput;
private var _sliderH:DraggableTextInput;
private var _ball:Shape;
private var _dummyBall:Sprite;
private function _onBallMouseDown(event:Event):void
{
_dummyBall.startDrag();
stage.addEventListener(MouseEvent.MOUSE_MOVE, _onBallMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, _onBallMouseUp);
}
private function _onBallMouseUp(event:MouseEvent):void
{
_dummyBall.stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_MOVE, _onBallMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, _onBallMouseUp);
}
private function _onBallMouseMove(event:MouseEvent):void
{
event.updateAfterEvent();
_sliderX.value = _ball.x = _dummyBall.x;
_sliderY.value = _ball.y = _dummyBall.y;
}
private function _onChange(event:Event):void
{
_ball.x = _dummyBall.x = _sliderX.value;
_ball.y = _dummyBall.y = _sliderY.value;
_ball.width = _dummyBall.width = _sliderW.value;
_ball.height = _dummyBall.height = _sliderH.value;
}
private function _onHeaderMouseDown(event:MouseEvent):void
{
_ui.startDrag();
stage.addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
}
private function _onMouseUp(event:MouseEvent):void
{
_ui.stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
}
private function _onMouseMove(event:MouseEvent):void
{
event.updateAfterEvent();
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.Capabilities;
import flash.system.IME;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.ui.Mouse;
/**
* 値が変更された直後に送出されます。
* @eventType flash.events.Event.CHANGE
*/
[Event(name="change", type="flash.events.Event")]
/**
* DraggableTextInput クラスはスライダーと直接入力の両方をサポートする数値入力インターフェースです。
* @author yasu
* @see http://clockmaker.jp/
*
*/
internal class DraggableTextInput extends Sprite
{
protected static const TEXTFORMAT_DEFAUT:TextFormat = new TextFormat("Arial", 11, 0x157bbe, null, null, true);
protected static const TEXTFORMAT_SLIDING:TextFormat = new TextFormat("Arial", 11, 0xFFFFFF, null, null, true);
protected static const TEXTFORMAT_INPUT:TextFormat = new TextFormat("Arial", 11, 0x000000, null, null, false);
protected static const TEXTFIELD_HEIGHT:Number = 21;
protected static const TEXTFIELD_WIDTH:Number = 50;
/**
* 新しい DraggableTextInput インスタンスを作成します。
*/
public function DraggableTextInput()
{
initialize();
}
/**
* ゼロ以外の場合、有効値は、このプロパティの整数倍と minimum の合計および maximum 以下になります。
* @return
*
*/
public function get snapInterval():Number
{
return _snapInterval;
}
public function set snapInterval(value:Number):void
{
if (value == 0)
throw new Error();
_snapInterval = value;
}
/**
* value の有効な最大値です。
*/
public function get maximum():Number
{
return _maximum;
}
public function set maximum(value:Number):void
{
_maximum = value;
_value = Math.min(_maximum, _value);
}
/**
* value の有効な最少値です。
*/
public function get minimum():Number
{
return _minimum;
}
public function set minimum(value:Number):void
{
_minimum = value;
_value = Math.max(_minimum, _value);
}
/**
* この範囲の現在の値です。
*/
public function get value():Number
{
return Number(_label.text);
}
public function set value(value:Number):void
{
_value = Math.max(_minimum, Math.min(_maximum, value));
_label.text = _format(_value);
}
/**
* 桁揃えの桁の数値です。
*/
public var formatRatio:int = -2;
protected var _value:Number;
protected var _label:TextField;
protected var _bg:Shape;
protected var _pointDown:Point;
protected var _focusShape:Shape;
protected var _valueOld:Number;
protected var _minimum:Number = int.MIN_VALUE;
protected var _maximum:Number = int.MAX_VALUE;
protected var _snapInterval:Number = 1;
protected var _isMouseDown:Boolean;
protected var _isMouseMove:Boolean;
private var _arrow:Bitmap;
/**
* インスタンスが保持しているデータを破棄します。
*/
public function finalize():void
{
_label.removeEventListener(Event.CHANGE, _onLabelChange);
removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
removeEventListener(MouseEvent.CLICK, _onClick);
}
protected function initialize():void
{
_bg = new Shape();
addChild(_bg);
_focusShape = new Shape();
_focusShape.graphics.beginFill(0x53b6f9);
_focusShape.graphics.drawRect(0, 0, 5, 5);
_focusShape.graphics.endFill();
_focusShape.graphics.beginFill(0x737373);
_focusShape.graphics.drawRect(1, 1, 3, 3);
_focusShape.graphics.endFill();
_focusShape.graphics.beginFill(0xFFFFFF);
_focusShape.graphics.drawRect(2, 2, 1, 1);
_focusShape.graphics.endFill();
_focusShape.scale9Grid = new Rectangle(2, 2, 1, 1);
addChild(_focusShape);
_focusShape.width = TEXTFIELD_WIDTH;
_focusShape.height = TEXTFIELD_HEIGHT;
_focusShape.visible = false;
_label = new TextField();
_label.type = TextFieldType.DYNAMIC;
_label.selectable = false;
_label.x = 2;
_label.y = 2;
_label.width = TEXTFIELD_WIDTH - 4;
_label.height = TEXTFIELD_HEIGHT - 4;
_label.restrict = "0-9.\\-";
_label.addEventListener(Event.CHANGE, _onLabelChange);
addChild(_label);
// use http://wonderfl.net/c/8TK2
var arr:Array = [
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0],
[0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0],
[0, 2, 1, 1, 2, 2, 2, 0, 2, 2, 2, 1, 1, 2, 0],
[2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 2],
[0, 2, 1, 1, 2, 2, 2, 0, 2, 2, 2, 1, 1, 2, 0],
[0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
];
var bmd:BitmapData = new BitmapData(15, 7, true, 0x0);
bmd.lock();
for (var i:int = 0; i < arr.length; i++)
{
for (var j:int = 0; j < arr[i].length; j++)
{
bmd.setPixel32(j, i, arr[i][j] == 0 ? 0x0 : arr[i][j] == 1 ? 0xFF000000 : 0xFFFFFFFF);
}
}
bmd.unlock();
_arrow = new Bitmap(bmd);
_label.defaultTextFormat = TEXTFORMAT_DEFAUT;
addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
addEventListener(MouseEvent.CLICK, _onClick);
}
protected function _onClick(event:MouseEvent):void
{
if (_isMouseDown)
return;
if (_focusShape.visible == true)
return;
if (Capabilities.hasIME)
{
try
{
IME.enabled = false;
}
catch (error:Error)
{
}
}
_valueOld = Number(_label.text);
_label.type = TextFieldType.INPUT;
_label.selectable = true;
_label.setSelection(0, _label.length);
_label.defaultTextFormat = TEXTFORMAT_INPUT;
_label.text = _label.text;
_focusShape.visible = true;
stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDownForCommit);
stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
}
protected function _onKeyDown(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.ENTER:
_commitProperties();
break;
case Keyboard.ESCAPE:
_label.text = _valueOld.toString(10);
_commitProperties();
break;
case Keyboard.UP:
_updateValue(Number(_label.text) + _snapInterval);
_label.setSelection(0, _label.length);
break;
case Keyboard.DOWN:
_updateValue(Number(_label.text) - _snapInterval);
_label.setSelection(0, _label.length);
break;
}
}
protected function _onMouseDownForCommit(event:MouseEvent):void
{
if (event.target == _label)
return;
_commitProperties();
}
protected function _commitProperties():void
{
var valueNew:Number = Number(_label.text);
if (valueNew < _minimum || valueNew > _maximum)
{
valueNew = _valueOld;
}
stage.removeEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
stage.removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseDownForCommit);
_label.defaultTextFormat = TEXTFORMAT_DEFAUT;
_label.selectable = false;
_label.type = TextFieldType.DYNAMIC;
_label.text = _format(valueNew)
_focusShape.visible = false;
_dispatchChangeEvent();
}
protected function _onMouseDown(event:MouseEvent):void
{
if (_label.type == TextFieldType.INPUT)
return;
stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
_label.defaultTextFormat = TEXTFORMAT_SLIDING;
_label.text = _label.text;
_pointDown = new Point(mouseX, mouseY);
_valueOld = Number(_label.text);
_bg.graphics.clear();
_bg.graphics.beginFill(0x157bbe);
_bg.graphics.drawRect(0, 0, _label.textWidth + 8, TEXTFIELD_HEIGHT);
Mouse.hide();
stage.addChild(_arrow);
_arrow.x = stage.mouseX - int( _arrow.width / 2 );
_arrow.y = stage.mouseY - int( _arrow.height / 2);
_isMouseDown = false;
_isMouseMove = false;
}
protected function _onMouseMove(event:MouseEvent):void
{
_isMouseMove = true;
var vx:Number = +1 * (mouseX - _pointDown.x);
var vy:Number = -1 * (mouseY - _pointDown.y);
var d:Number = (vx + vy) * _snapInterval;
_updateValue(_valueOld + d);
_bg.graphics.clear();
_bg.graphics.beginFill(0x157bbe);
_bg.graphics.drawRect(0, 0, _label.textWidth + 8, TEXTFIELD_HEIGHT);
_dispatchChangeEvent();
_arrow.x = stage.mouseX - int( _arrow.width / 2 );
_arrow.y = stage.mouseY - int( _arrow.height / 2);
}
protected function _updateValue(valueNew:Number):void
{
valueNew = Math.max(_minimum, Math.min(_maximum, valueNew));
_label.text = _format(valueNew);
}
protected function _onMouseUp(event:MouseEvent):void
{
_bg.graphics.clear();
stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
_label.defaultTextFormat = TEXTFORMAT_DEFAUT;
_label.text = _label.text;
if (event.target == _label && _isMouseMove)
_isMouseDown = true;
Mouse.show();
stage.removeChild(_arrow);
}
/**
* 値をフォーマットします。
* @param val フォーマットしたい値。
* @return フォーマットされた文字列。
*/
protected function _format(val:Number):String
{
var nn:Number = Math.pow(10, formatRatio);
var valueNew:Number = Math.round(val / nn) * nn;
var str:String = valueNew.toString(10);
var arr:Array = str.split(".");
var decimal:String = arr[1] || "00";
var ratio:Number = Math.abs(formatRatio);
if (decimal.length < ratio)
{
while (decimal.length < ratio)
{
decimal = decimal + "0";
}
}
else
{
decimal = decimal.substr(0, ratio);
}
if (ratio == 0)
decimal = "0";
return arr[0] + "." + decimal;
}
protected function _dispatchChangeEvent():void
{
dispatchEvent(new Event(Event.CHANGE));
}
private function _onLabelChange(event:Event):void
{
event.stopPropagation();
}
}