mindmap tool
マインドマップツール試作品
/**
* Copyright dory ( http://wonderfl.net/user/dory )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/t2xQ
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Video;
import flash.utils.getDefinitionByName;
/**
* マインドマップツール試作品
* メインクラス
* @author dory
*/
[SWF(backgroundColor="0x000000", width="465", height="465", frameRate="60" )]
public class Main extends Sprite
{
public static var instance:Main;
public var balloonSprite:Sprite;
public var lineSprite:Sprite;
public static var color:uint = 0xffffff;
public static var cornerRadius:Number = 0; // 角丸
public static const STAGE_WIDTH:Number = 465;
public static const STAGE_HEIGHT:Number = 465;
private var _rootBalloon:RootBalloon;
private var _effect:Effect;
public function Main():void
{
instance = this;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
createBack(); // 背景・エフェクトなど
balloonSprite = new Sprite(); // バルーン用スプライト
addChild( balloonSprite );
lineSprite = new Sprite; // ライン用スプライト
addChild( lineSprite );
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
addEventListener( MouseEvent.CLICK, clickHandler );
addEventListener( BalloonEvent.EFFECT, balloonEffectHandler );
addEventListener( BalloonEvent.MOVE, balloonMoveHandler );
}
/**
* 描画更新
* @param event
*/
private function enterFrameHandler( event:Event ):void {
_effect.update(); // エフェクトの描画更新
}
/**
* ルートバルーンを追加。一度だけ使用
* @param evnet
*/
private function clickHandler( evnet:MouseEvent ):void {
_rootBalloon = new RootBalloon();
_rootBalloon.birth();
removeEventListener( MouseEvent.CLICK, clickHandler );
}
/**
* バルーンに何かしたときのエフェクト
* @param event
*/
private function balloonEffectHandler( event:BalloonEvent ):void {
if ( event.balloon )
_effect.rebirth( event.balloon.x, event.balloon.y );
}
/**
* ドラッグ中ラインの描画更新
* @param event
*/
private function balloonMoveHandler( event:BalloonEvent ):void {
lineSprite.graphics.clear();
_rootBalloon.redraw();
}
/**
* 背景の作成
*/
private function createBack():void {
var back:Sprite = new Sprite();
back.graphics.beginFill( 0x333366 );
back.graphics.drawRect( 0, 0, STAGE_WIDTH, STAGE_HEIGHT );
back.graphics.endFill();
addChild( back );
_effect = new Effect();
addChild( _effect );
}
}
}
/**
* 定数クラス
* @author dory
*/
class Const
{
public static const PADDING:Number = 10.0;
}
/**
* エフェクトクラス
* @author dory
*/
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.BlendMode;
import flash.geom.ColorTransform
class Effect extends Sprite
{
private const BITMAP_COL:uint = 0x0000ffff;
private const LIGHT_MAX:int = 50;
private const CHANGE_COL_SPEED:int = 2;
private const BASE_COL:uint = 0xcc;
private const MIN_COL:uint = 0x00;
private var _container:Sprite;
private var _lightList:Array;
private var _colorTrans:ColorTransform;
private var _blur:BlurFilter;
private var _bitmapData:BitmapData;
private var _bitmap:Bitmap;
private var _rect:Rectangle;
private var _point:Point;
private var _changeCol:uint = MIN_COL;
private var _dc:int = CHANGE_COL_SPEED;
public function Effect()
{
birth();
}
/**
* 生成
*/
private function birth():void {
_rect = new Rectangle( 0, 0, Main.STAGE_WIDTH, Main.STAGE_HEIGHT );
_point = new Point( 0, 0 );
_bitmapData = new BitmapData( Main.STAGE_WIDTH, Main.STAGE_HEIGHT, true, BITMAP_COL);
_bitmap = new Bitmap( _bitmapData );
addChild(_bitmap);
_lightList = new Array();
_container = new Sprite();
addChild( _container );
_colorTrans = new ColorTransform();
_colorTrans.color = BASE_COL << 16 | BASE_COL << 8 | BASE_COL;
_blur = new BlurFilter(8, 8, 3);
var light:Light;
for (var i:int = 0; i < LIGHT_MAX; i++) {
light = new Light();
light.birth();
_container.addChild(light );
_lightList.push( light );
}
}
/**
* 再生成
* @param x
* @param y
*/
public function rebirth( x:Number, y:Number ):void {
for each ( var light:Light in _lightList ) {
light.birth( x, y );
}
}
/**
* 描画更新
*/
public function update():void {
_bitmapData.lock();
for ( var i:int = 0; i < _lightList.length; i++ ) {
var light:Light = _lightList[ i ];
light.move();
}
colorChange();
_bitmapData.draw( _container, null, _colorTrans, BlendMode.SCREEN, null, true );
_bitmapData.applyFilter( _bitmapData, _rect, _point, _blur );
_bitmapData.unlock();
}
/**
* 色の変更
*/
private function colorChange():void {
_changeCol += _dc;
if ( _changeCol < MIN_COL ) {
_changeCol = MIN_COL;
_dc = CHANGE_COL_SPEED;
} else if ( _changeCol > BASE_COL ) {
_changeCol = BASE_COL;
_dc = -CHANGE_COL_SPEED;
}
_colorTrans.color = _changeCol << 16 | _changeCol << 8 | BASE_COL;
}
}
/**
* 光クラス
* @author dory
*/
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.BlendMode;
class Light extends Sprite
{
private const MAX_ALPHA_SPEED:Number = 0.05;
private const MIN_ALPHA_SPEED:Number = 0.005;
private const MAX_SIZE:Number = 6;
private const MIN_SIZE:Number = 1;
private const MAX_SPEED:Number = 0.2;
private const MIN_SPEED:Number = -( MAX_SPEED / 8 );
private var _color:uint = 0xFFFFFF;
private var _targetX:Number;
private var _targetY:Number;
private var _dx:Number;
private var _dy:Number;
private var _dalpha:Number;
private var _rad:Number;
public function Light()
{
blendMode = BlendMode.ADD;
}
/**
* 生成
* @param x
* @param y
*/
public function birth( x:Number = Main.STAGE_WIDTH / 2, y:Number = Main.STAGE_HEIGHT / 2 ):void {
alpha = 1;
_targetX = x;
_targetY = y;
_rad = Math.random() * MAX_SIZE + MIN_SIZE;
_dx = Math.random() * MAX_SPEED + MIN_SPEED;
_dy = Math.random() * MAX_SPEED + MIN_SPEED;
_dalpha = Math.random() * MAX_ALPHA_SPEED + MIN_ALPHA_SPEED;
draw();
x = Main.STAGE_WIDTH * Math.random();
y = Main.STAGE_HEIGHT * Math.random();
}
/**
* 描画
*/
private function draw():void {
graphics.beginFill( _color );
graphics.drawCircle( 0, 0, _rad );
graphics.endFill();
}
/**
* 移動処理
*/
public function move():void {
x += ( _targetX - x ) * _dx;
y += ( _targetY - y ) * _dy;
alpha -= _dalpha;
if ( alpha < 0 ) {
graphics.clear();
}
}
}
import flash.events.Event;
/**
* バルーン関係のイベントクラス
* @author Yoshimura Miho
*/
class BalloonEvent extends Event
{
public static const EFFECT:String = "effect";
public static const MOVE:String = "move";
public var balloon:BalloonBase;
public function BalloonEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, balloon:BalloonBase = null )
{
super( type, bubbles, cancelable );
this.balloon = balloon;
}
}
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldType;
import flash.events.KeyboardEvent;
/**
* バルーン基底クラス
* @author dory
*/
class BalloonBase extends Sprite
{
private const DEFAULT_TEXT:String = "Main Topic";
private const LINE_TICKNESS:Number = 2;
private const LINE_COL:uint = 0xffffff;
// バルーンとバルーンのデフォルトの距離
private const AWAY_X:Number = 100;
private const AWAY_Y:Number = 50;
private var _parentBalloon:BalloonBase; // 親のバルーン
public var childBalloons:Array = new Array(); // 子のバルーン
private var _moved:Boolean = false; // ドラッグ中
protected var textField:TextField = new TextField();
public function BalloonBase()
{
createTextField();
}
/**
* テキストフィールド作成
*/
private function createTextField():void {
textField.text = DEFAULT_TEXT;
textField.width = textField.textWidth + Const.PADDING;
textField.height = textField.textHeight + Const.PADDING;
textField.selectable = false;
textField.type = TextFieldType.DYNAMIC;
textField.addEventListener( MouseEvent.DOUBLE_CLICK, tfDoubleClickHandler );
textField.doubleClickEnabled = true;
addChild( textField );
}
/**
* バルーン生成
* @param parent
*/
public function birth( parent:BalloonBase = null ):void {
_parentBalloon = parent;
draw();
initPos();
drawLine();
addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
addEventListener( MouseEvent.CLICK, clickHandler );
stage.addEventListener( MouseEvent.CLICK, stageClickHandler );
dispatchEvent( new BalloonEvent( BalloonEvent.EFFECT, true, false, this ) );
}
/**
* デフォルトポジション設定
*/
private function initPos():void {
if ( _parentBalloon ) {
if ( _parentBalloon.childBalloons.length % 2 == 0 )
this.x = _parentBalloon.x + AWAY_X
else
this.x = _parentBalloon.x - AWAY_X
this.y = _parentBalloon.y + int( _parentBalloon.childBalloons.length / 2 ) * AWAY_Y;
} else {
this.x = stage.stageWidth / 2 - this.width / 2;
this.y = stage.stageHeight / 2 - this.height / 2;
}
}
/**
* マウスダウン
* @param event
*/
private function mouseDownHandler( event:MouseEvent ):void {
if ( textField.selectable ) return;
_moved = false;
stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler );
stage.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
}
/**
* マウスムーブ
* @param event
*/
private function mouseMoveHandler( event:MouseEvent ):void {
_moved = true;
this.x = Main.instance.mouseX - this.width / 2;
this.y = Main.instance.mouseY - this.height / 2;
dispatchEvent( new BalloonEvent( BalloonEvent.MOVE, true ) );
}
/**
* マウスアップ
* @param event
*/
private function mouseUpHandler( event:MouseEvent ):void {
stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler );
stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
if ( _moved ) // ドラッグの後エフェクト
dispatchEvent( new BalloonEvent( BalloonEvent.EFFECT, true, false, this ) );
}
/**
* バルーンクリック
* @param event
*/
private function clickHandler( event:MouseEvent ):void {
if ( event.target is TextField && textField.selectable ) { // 編集中はバルーン生成しない
return;
}
if ( _moved ) return;
var child:BalloonBase;
if ( _parentBalloon )
child = new ThirdBalloon();
else
child = new SecondBalloon();
child.birth( this );
childBalloons.push( child );
}
/**
* ステージクリック。編集終了用
* @param event
*/
private function stageClickHandler( event:MouseEvent ):void {
if ( event.target is BalloonBase || event.target is TextField )
return;
textField.selectable = false;
textField.type = TextFieldType.DYNAMIC;
}
/**
* テキストフィールドダブルクリック
* @param event
*/
private function tfDoubleClickHandler( event:MouseEvent ):void {
textField.selectable = true;
textField.type = TextFieldType.INPUT;
}
/**
* バルーンの描画
*/
protected function draw():void {
if ( !Main.instance.contains( this ) )
Main.instance.balloonSprite.addChild( this );
graphics.clear();
// 継承クラスで描画
}
/**
* 描画更新
*/
public function redraw():void {
drawLine();
for each ( var child:BalloonBase in childBalloons ) {
child.redraw();
}
}
/**
* ラインの描画
*/
public function drawLine():void {
if ( !_parentBalloon ) return;
var startx:Number;
var starty:Number;
var endx:Number;
var endy:Number;
if ( _parentBalloon.x > this.x ) { // 左側
startx = this.x + this.width;
endx = _parentBalloon.x;
starty = this.y + this.height / 2;
endy = _parentBalloon.y + _parentBalloon.height / 2;
} else { // 右側
startx = _parentBalloon.x + _parentBalloon.width;
endx = this.x;
starty = _parentBalloon.y + _parentBalloon.height / 2;
endy = this.y + this.height / 2;
}
Main.instance.lineSprite.graphics.lineStyle( LINE_TICKNESS, LINE_COL );
Main.instance.lineSprite.graphics.moveTo( startx, starty );
Main.instance.lineSprite.graphics.lineTo( endx, endy );
}
}
import flash.display.GradientType;
import flash.geom.Matrix;
/**
* ルートのバルーンのデザイン
* @author dory
*/
class RootBalloon extends BalloonBase
{
private const THICKNESS:uint = 3;
private const LINE_COLOR:uint = 0x3333cc;
private const ALPHAS:Array = [ 0.6, 0.6 ];
private const RATIOS:Array = [ 0, 255 ];
private const FILL_COLORS:Array = [ 0xffffff, LINE_COLOR ];
private const CORNER_RADIUS:Number = 10.0;
public function RootBalloon()
{
}
override protected function draw():void {
super.draw();
graphics.lineStyle( THICKNESS, LINE_COLOR );
var matrix:Matrix = new Matrix();
var w:Number = textField.textWidth + Const.PADDING;
var h:Number = textField.textHeight + Const.PADDING;
matrix.createGradientBox( w, h, 90 );
graphics.beginGradientFill( GradientType.LINEAR, FILL_COLORS, ALPHAS, RATIOS, matrix );
graphics.drawRoundRect( 0, 0, w, h, CORNER_RADIUS, CORNER_RADIUS );
graphics.endFill();
}
}
import flash.display.GradientType;
/**
* 2階層目のバルーンのデザイン
* @author dory
*/
class SecondBalloon extends BalloonBase
{
private const THICKNESS:uint = 1;
private const LINE_COLOR:uint = 0xcccccc;
private const ALPHAS:Array = [ 0.8, 0.8 ];
private const RATIOS:Array = [ 0, 127 ];
private const FILL_COLORS:Array = [ 0xffffff, LINE_COLOR ];
private const CORNER_RADIUS:Number = 10.0;
private const PADDING:Number = 10.0;
public function SecondBalloon()
{
}
override protected function draw():void {
super.draw();
graphics.lineStyle( THICKNESS, LINE_COLOR );
graphics.beginGradientFill( GradientType.LINEAR, FILL_COLORS, ALPHAS, RATIOS );
var w:Number = textField.textWidth + PADDING;
var h:Number = textField.textHeight + PADDING;
graphics.drawRoundRect( 0, 0, w, h, CORNER_RADIUS, CORNER_RADIUS );
graphics.endFill();
}
}
import flash.display.GradientType;
/**
* 3階層目のバルーンのデザイン
* @author dory
*/
class ThirdBalloon extends BalloonBase
{
private const UNDER_THICKNESS:uint = 1;
private const UNDER_LINE_COLOR:uint = 0xcccccc;
private const COLOR:uint = 0xffffff;
private const PADDING:Number = 10.0;
public function ThirdBalloon()
{
}
override protected function draw():void {
super.draw();
graphics.beginFill( COLOR );
var w:Number = textField.textWidth + PADDING;
var h:Number = textField.textHeight + PADDING;
graphics.drawRect( 0, 0, w, h );
graphics.endFill();
graphics.lineStyle( UNDER_THICKNESS, UNDER_LINE_COLOR );
graphics.moveTo( 0, h );
graphics.lineTo( w, h );
}
}