forked from: 円グラフとスライドバー

by steven forked from 円グラフとスライドバー (diff: 1)
♥0 | Line 393 | Modified 2010-03-10 16:53:15 | MIT License
play

ActionScript3 source code

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

// forked from Nyarineko's 円グラフとスライドバー
// forked from nengafl's nengafl
/*
以下のソースを流用させて頂きました。
http://wonderfl.net/code/e56d03cafa31cb51fdb9fd0eca341b3fb96a3975
http://wonderfl.net/code/f16c8b8e3c5cc1044eb417b0098ec71d115420c3
*/
package
{
	import flash.display.*;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	public class Main extends Sprite {
	
		public var chart:PieChart3D;
		
		private var slider1Min:Number = 0;
		private var slider1Max:Number = 100;
		private var slider2Min:Number = 0;
		private var slider2Max:Number = 200;
		
		public var RAD:Number = 130;
		
		private var slider1:slider = new slider("A",400, 20, slider1Max, slider1Min, stage);
		private var slider2:slider = new slider("B",400, 20, slider1Max, slider1Min, stage);
		private var slider3:slider = new slider("C",400, 20, slider2Max, slider2Min, stage);
		private var slider4:slider = new slider("D",400, 20, slider2Max, slider2Min, stage);
		
		public function Main(){
			stage.scaleMode = "noScale";
			
			addChild(slider1);
			slider1.addEventListener(slider.SLIDE, calc);
			slider1.x = 40;
			slider1.y = 20;
			
			addChild(slider2);
			slider2.addEventListener(slider.SLIDE, calc);
			slider2.x = 40;
			slider2.y = 45;
			
			addChild(slider3);
			slider3.addEventListener(slider.SLIDE, calc);
			slider3.x = 40;
			slider3.y = 70;
			
			addChild(slider4);
			slider4.addEventListener(slider.SLIDE, calc);
			slider4.x = 40;
			slider4.y = 95;
			
			slider1.scalePosition = 0.5;
			slider2.scalePosition = 0.5;
			slider3.scalePosition = 0.5;
			slider4.scalePosition = 0.5;
			
			chart = new PieChart3D();
			chart.x = 465 / 2;
			chart.y = 280;
			chart.pieRadius = RAD;
			chart.addData( new PieChartData( "A", slider1.position ) );
			chart.addData( new PieChartData( "B", slider2.position ) );
			chart.addData( new PieChartData( "C", slider3.position ) );
			chart.addData( new PieChartData( "D", slider4.position ) );
			chart.startDraw();
			addChild(chart);
		}
		
		private function calc(e:Event = null):void {
			if(!(slider1.position == 0 && slider2.position == 0 && slider3.position == 0 && slider4.position == 0)){
				removeChild(chart);
				chart = new PieChart3D();
				chart.x = 465 / 2;
				chart.y = 280;
				chart.pieRadius = RAD;
				chart.addData( new PieChartData( "A", slider1.position ) );
				chart.addData( new PieChartData( "B", slider2.position ) );
				chart.addData( new PieChartData( "C", slider3.position ) );
				chart.addData( new PieChartData( "D", slider4.position ) );
				chart.startDraw();
				addChild(chart);
			}
		}
	}
}

import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
class PieChart3D extends Sprite {
	
	private static const PI2:Number = 0.01746;
	
	public static var S:int = 1;
	public static var V:int = 1;
	
	public var data:Array;
	public var sum:Number;
	
	// グラフの半径
	public var pieRadius:Number;
	// グラフの高さ
	public var pieHeight:Number = 20;
	// グラフの傾き
	public var pieGradientAngle:Number = 80;
	
	private var _currentIndex:Number;
	private var _currentAngle:Number;
	
	private var _pies:Array;
	
	public function get numData():int { return data.length; }
	
	public function PieChart3D():void {
		data = [];
	}
	
	public function addData(data:PieChartData):PieChartData {
		this.data.push(data);
		return data;
	}
	
	public function getDataAt(index:int):PieChartData {
		return data[index] as PieChartData;
	}
	
	public function getPieAt(index:int):Sprite {
		return _pies[index] as Sprite;
	}
	
	public function startDraw():void {
		while (numChildren) { removeChildAt(numChildren-1); }
		// 初期設定
		_pies = [];
		_initialize();
		_currentAngle = 
		_currentIndex = 0;
		_draw();
	}
	
	private function _draw():void {
		_currentAngle++;
		var pie:Sprite = getPieAt(_currentIndex);
		if (!pie) { return; }
		pie.graphics.clear();
		
		var d:PieChartData = getDataAt(_currentIndex);
		if ( _currentAngle > d.endAngle) { _currentAngle = d.endAngle; }
		var a:Number, b:Number;
		var kh:Number = pieGradientAngle / 90;
		
		var ang:Number, sep:Number, sepang:Number, r:Number, rs:Number, re:Number,rt:Number, i:int;
		
		// 外壁
		if (_currentAngle > 90 && ((d.startAngle < 180 && d.endAngle >= 90) || (d.endAngle >= 90 && d.startAngle < 270))) {
			var colors:Array = [d.color1, d.color2];
			var alphas:Array = [100, 100];
			var ratios:Array = [0, 0xFF];
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(pieRadius * 2, pieRadius * 2, 0, pieRadius, pieRadius * kh);
			pie.graphics.beginGradientFill("linear", colors, alphas, ratios, matrix);
			var startAngle:Number = Math.max(d.startAngle, 90);
			var endAngle:Number = Math.min(_currentAngle, 270);
			ang = endAngle - startAngle;
			sep = Math.ceil(ang / 30);
			sepang = ang / sep;
			r = pieRadius / Math.cos(sepang / 2 * PI2);
			pie.graphics.moveTo(_getX(startAngle) * pieRadius, _getY(startAngle) * pieRadius * kh);
			for ( i = 0; i < sep; i++ ) {
				pie.graphics.lineTo(_getX(startAngle + sepang * i) * pieRadius, _getY(startAngle + sepang * i) * pieRadius * kh + pieHeight);
				pie.graphics.curveTo(_getX(startAngle + sepang * i + sepang / 2) * r, _getY(startAngle + sepang * i + sepang / 2) * r * kh + pieHeight, _getX(startAngle + sepang * (i + 1)) * pieRadius, _getY(startAngle + sepang * (i + 1)) * pieRadius * kh + pieHeight);
				pie.graphics.lineTo(0, 0);
			}
			pie.graphics.lineTo(_getX(endAngle) * pieRadius, _getY(endAngle) * pieRadius * kh + pieHeight);
			pie.graphics.lineTo(_getX(endAngle) * pieRadius, _getY(endAngle) * pieRadius * kh);
			pie.graphics.endFill();
		}
		
		// 上面
		ang = _currentAngle - d.startAngle;
		sep = Math.ceil(ang / 30);
		sepang = ang / sep;
		r = pieRadius / Math.cos(sepang / 2 * PI2);
		pie.graphics.beginFill(d.color);
		for (i = 0; i < sep; i++) {
			pie.graphics.moveTo(0, 0);
			pie.graphics.lineTo(_getX(d.startAngle + sepang * i) * pieRadius, _getY(d.startAngle + sepang * i) * pieRadius * kh);
			pie.graphics.curveTo(_getX(d.startAngle + sepang * i + sepang / 2) * r, _getY(d.startAngle + sepang * i + sepang / 2) * r * kh, _getX(d.startAngle + sepang * (i + 1)) * pieRadius, _getY(d.startAngle + sepang * (i + 1)) * pieRadius * kh);
			pie.graphics.lineTo(0, 0);
		}
		pie.graphics.endFill();
		
		if(Math.floor(_currentAngle) == (Math.floor(d.startAngle + (d.endAngle-d.startAngle)/2))){
			trace(_currentAngle);
			rs = (pieRadius - 5) / Math.cos(sepang / 2 * PI2);
			re = (pieRadius + 30) / Math.cos(sepang / 2 * PI2);
			rt = (pieRadius + 40) / Math.cos(sepang / 2 * PI2);
			var pie2:Sprite = new Sprite();
			pie2.graphics.lineStyle (1,0x000000,1,true,"none","none","miter");
			pie2.graphics.moveTo(_getX(d.startAngle + sepang * i + sepang / 2) * rs, _getY(d.startAngle + sepang * i + sepang / 2) * rs * kh);
			pie2.graphics.lineTo(_getX(d.startAngle + sepang * i + sepang / 2) * re, _getY(d.startAngle + sepang * i + sepang / 2) * re * kh);
			
			
			var txt:TextField = new TextField();
			txt.defaultTextFormat = new TextFormat(null, null, 0x000000);
			txt.text = d.name + ":" + d.value.toString();
			txt.autoSize = TextFieldAutoSize.LEFT;
			txt.selectable = false;
			txt.x = _getX(d.startAngle + sepang * i + sepang / 2) * rt - 7;
			txt.y = _getY(d.startAngle + sepang * i + sepang / 2) * rt * kh - 7;
			
			pie2.graphics.beginFill(0xFFFFFF, 1);
			pie2.graphics.drawRoundRect(txt.x - 1, txt.y - 1, txt.width +2, txt.height, 10);
			pie2.graphics.endFill();
			
			addChild(pie2);
			addChild(txt);
		}
		
		if (_currentAngle >= d.endAngle) {
			_currentIndex++;
			if (_currentIndex >= numData) {
				//
			}else{
				_draw();
			}
		}else{
			_draw();
		}
	}
	
	private function _getX(angle:Number):Number { return Math.cos((angle - 90) * PI2); }
	private function _getY(angle:Number):Number { return Math.sin((angle - 90) * PI2); }
	
	private function _initialize():void {
		// 合計
		sum = 0;
		data.forEach(function(item:*, index:int, arr:Array):void { sum += item.value; } );
		// 多い順にソート
		//data.sortOn("value", Array.DESCENDING | Array.NUMERIC);
		var angle:Number = 0;
		var swapArr:Array = [];
		for (var i:int = 0, l:int = numData; i < l; i++)  {
			var d:PieChartData = data[i];
			// 角度
			d.startAngle = angle;
			d.endAngle = angle + d.value / sum * 360;
			var argAngle:Number = (d.endAngle - d.startAngle) / 2 + d.startAngle
			swapArr.push({ index:i, lebel:argAngle > 180 ? 360 - argAngle : argAngle });
			// 色
			var c:int = d.color = angle2RGB(i * 360 / l);
			var r1:int = Math.max(0, ((c >> 16) - 0x22));
			var r2:int = Math.max(0, ((c >> 16) - 0x44));
			c %= 0x10000;
			var g1:int = Math.max(0, ((c >> 8) - 0x22));
			var g2:int = Math.max(0, ((c >> 8) - 0x44));
			c %= 0x100;
			var b1:int = Math.max(0, (c - 0x22));
			var b2:int = Math.max(0, (c - 0x44));
			d.color1 = r1 << 16 | g1 << 8 | b1;
			d.color2 = r2 << 16 | g2 << 8 | b2;
			angle = d.endAngle;
		}
		// 表示順のZソートして Sprite 作成
		swapArr.sortOn("lebel", Array.NUMERIC);
		swapArr.forEach(function(item:*, index:int, arr:Array):void {
			var pie:Sprite = new Sprite();
			addChild(pie);
			_pies[item["index"]] = pie;
		});
	}
	
	private function angle2RGB(angle:Number):uint {
		if ( angle < 0 ) { angle += 360; }
		angle %= 360;
		var h:int = Math.floor( angle / 60 );
		var f:Number = angle / 60 - h;
		var min:int = 0;
		var max:int = 0xFF;
		var u:int = min + ( f * max );
		var d:int = max - ( f * max );
		var r:int, g:int, b:int;
		switch (h) {
			case 0 : { r = max; g = u;   b = min; break; }
			case 1 : { r = d;   g = max; b = min; break; }
			case 2 : { r = min; g = max; b = u;   break; }
			case 3 : { r = min; g = d;   b = max; break; }
			case 4 : { r = u;   g = min; b = max; break; }
			case 5 : { r = max; g = min; b = d;   break; }
		}
		return r << 16 | g << 8 | b;
	}
	
}

class PieChartData {
	public var name:String;
	public var value:Number;
	public var color:int;
	public var color1:int;
	public var color2:int;
	public var startAngle:Number;
	public var endAngle:Number;
	public var lebel:int;
	
	public function PieChartData(name:String, value:Number) {
		this.name = name;
		this.value = value;
	}
}


import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
internal class slider extends Sprite {
	
	public static const SLIDE:String = "slide";
	
	private var _drag:Boolean = false;
	private var _rollOverFlag:Boolean = false;
	
	private var _w:Number;
	private var _h:Number;
	
	private var _position:Number;
	private var _scalePosition:Number;
	private var _positionMax:Number;
	private var _positionMin:Number;
	
	private	var sliderA:Sprite = new Sprite();
	private var sliderB:Sprite = new Sprite();
	private var toolTip:Sprite = new Sprite();
	private var toolTipBG:Sprite = new Sprite();
	private var toolTipTxt:TextField = new TextField();
	
	public function slider(slide:String, w:Number, h:Number, max:Number, min:Number, dObj:DisplayObject) {
		_w = w;
		_h = h;
		_positionMax = max;
		_positionMin = min;
		
		//スライダーの溝を描画
		sliderA.graphics.lineStyle(2, 0x555555);
		sliderA.graphics.moveTo(0, _h / 2);
		sliderA.graphics.lineTo(_w, _h / 2);
		
		addChild(sliderA);
		
		var txt:TextField = new TextField();
		txt.defaultTextFormat = new TextFormat(null, null, 0x333333);
		txt.text = slide;
		txt.autoSize = TextFieldAutoSize.LEFT;
		txt.selectable = false;
		txt.x = -25;
		txt.y = 0;
		addChild(txt);
		
		//パラメータの最大値最小値を書いておく
		var txt1:TextField = new TextField();
		txt1.defaultTextFormat = new TextFormat(null, null, 0xAAAAAA);
		txt1.text = _positionMax.toString();
		txt1.autoSize = TextFieldAutoSize.LEFT;
		txt1.selectable = false;
		txt1.x = _w - txt1.width / 2;
		txt1.y = _h / 2;
		addChild(txt1);
		
		var txt2:TextField = new TextField();
		txt2.defaultTextFormat = new TextFormat(null, null, 0xAAAAAA);
		txt2.text = _positionMin.toString();
		txt2.autoSize = TextFieldAutoSize.LEFT;
		txt2.selectable = false;
		txt2.x = -txt1.width / 2;
		txt2.y = _h / 2;
		addChild(txt2);
		
		//スライダーのツマミを描画
		sliderB.graphics.beginFill(0x000000);
		sliderB.graphics.drawRoundRect(-5, 0, 10, h, 5);
		sliderB.graphics.endFill();
		sliderB.buttonMode = true;
		
		addChild(sliderB);
		
		//ツールチップを描画
		var tf:TextFormat = new TextFormat();
		tf.color = 0xFFFFFF;
		tf.leftMargin = 5;
		tf.rightMargin = 5;
		toolTipTxt.defaultTextFormat = tf;
		toolTipTxt.autoSize = TextFieldAutoSize.LEFT;
		toolTipTxt.selectable = false;
		
		toolTip.addChild(toolTipBG);
		toolTip.addChild(toolTipTxt);
		addChild(toolTip);
		toolTip.visible = false;
		
		//addEventListener
		sliderB.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
		dObj.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
		dObj.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler);
		sliderB.addEventListener(MouseEvent.MOUSE_OVER, onMouseOverHandler);
		sliderB.addEventListener(MouseEvent.MOUSE_OUT, onMouseOutHandler);
		
		_scalePosition = this.scalePosition;
		_position = this.position;
	}
	private function onMouseMoveHandler(e:MouseEvent = null):void 
	{		
		if (_drag) {
			_scalePosition = this.scalePosition;
			_position = this.position;
			dispatchEvent(new Event(SLIDE));
		}
		
		if (_rollOverFlag) showPosition(new Point(e.stageX, e.stageY));
	}
	private function onMouseDownHandler(e:MouseEvent):void 
	{
		_drag = true;
		e.target.startDrag(false,new Rectangle(0,0,_w,0));
	}
	private function onMouseUpHandler(e:MouseEvent):void 
	{
		_drag = false;
		_rollOverFlag = false;
		toolTip.visible = false;
		sliderB.stopDrag();
	}
	private function onMouseOverHandler(e:MouseEvent):void 
	{
		_rollOverFlag = true;
		toolTip.visible = true;
		
		showPosition(new Point(e.stageX, e.stageY));
	}
	private function showPosition(arg1:Point):void 
	{
		var pt:Point = globalToLocal(arg1);
		
		toolTip.x = pt.x + 15;
		toolTip.y = pt.y;
		
		toolTipTxt.text = "value = " + _position;
		toolTipBG.graphics.clear();
		toolTipBG.graphics.beginFill(0x000000, .5);
		toolTipBG.graphics.drawRoundRect(0, -5, toolTipTxt.width, toolTipTxt.height+10, 10);
		toolTipBG.graphics.endFill();
	}
	private function onMouseOutHandler(e:MouseEvent):void 
	{
		if (!_drag) {
			_rollOverFlag = false;
			toolTip.visible = false;
		}
	}
	//get/set
	public function get position():Number {
		_scalePosition = this.scalePosition;
		return Math.floor((_positionMax - _positionMin) * _scalePosition + _positionMin);
	}
	public function set position(pos:Number):void {
		_position = pos;
		_scalePosition = (_position - _positionMin) / (_positionMax - _positionMin);
		sliderB.x = _w * _scalePosition;
	}
	public function get scalePosition():Number {
		_scalePosition = sliderB.x / _w;
		return _scalePosition;
	}
	public function set scalePosition(posScale:Number):void {
		_scalePosition = posScale;
		_position = (_positionMax - _positionMin) * _scalePosition + _positionMin;
		sliderB.x = _w * _scalePosition;
	}
}