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: PieChart

円グラフ
3Dを使わないで3Dっぽく円グラフを作ってみた
Get Adobe Flash player
by tepe 24 Jan 2011
/**
 * Copyright tepe ( http://wonderfl.net/user/tepe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/t9Xa
 */

// forked from cuegraphix's PieChart
/**
 * 円グラフ
 * 3Dを使わないで3Dっぽく円グラフを作ってみた
 */
package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    [SWF(width=465, height=465, backgroundColor=0xFFFFFF, frameRate=60)]
    
    public class PieChart extends Sprite {
        
        public var chart:PieChart3D;
        
        public function PieChart() {
            Wonderfl.capture_delay( 2 );
            stage.scaleMode = "noScale";
            
            chart = new PieChart3D();
            chart.x = 465 / 2;
            chart.y = 465 / 2;
            chart.pieRadius = 150;
            
            chart.addData( new PieChartData( "A", 120 ) );
            chart.addData( new PieChartData( "B", 228 ) );
            chart.addData( new PieChartData( "C", 15 ) );
            chart.addData( new PieChartData( "D", 362 ) );
            chart.addData( new PieChartData( "E", 106 ) );
            chart.addData( new PieChartData( "F", 149 ) );
            chart.addData( new PieChartData( "G", 8 ) );
            
            addChild(chart);
            
            stage.addEventListener(MouseEvent.CLICK, _click);
            _click();
        }
        
        private function _click(e:MouseEvent = null):void {
            chart.startDraw();
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
class PieChart3D extends Sprite {
    
    private static const PI2:Number = 0.01745;
    
    public static var S:int = 1;
    public static var V:int = 1;
    
    public var data:Array;
    public var sum:Number;
    
    // グラフの半径
    public var pieRadius:Number = 100;
    // グラフの高さ
    public var pieHeight:Number = 20;
    // グラフの傾き
    public var pieGradientAngle:Number = 75;
    
    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 {
        stopDraw();
        while (numChildren) { removeChildAt(numChildren-1); }
        // 初期設定
        _pies = [];
        _initialize();
        _currentAngle = 
        _currentIndex = 0;
        addEventListener(Event.ENTER_FRAME, _draw);
    }
    
    public function stopDraw():void {
        removeEventListener(Event.ENTER_FRAME, _draw);
    }
    
    private function _draw(e:Event):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;
        // 断面
        a = _getX(_currentAngle) * pieRadius;
        b = _getY(_currentAngle) * pieRadius * kh;
        pie.graphics.beginFill(d.color1);
        pie.graphics.moveTo(0, 0);
        pie.graphics.lineTo(0, pieHeight);
        pie.graphics.lineTo(a, b + pieHeight);
        pie.graphics.lineTo(a, b);
        pie.graphics.endFill();
        
        var ang:Number, sep:Number, sepang:Number, r: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 (_currentAngle >= d.endAngle) {
            _currentIndex++;
            if (_currentIndex >= numData) {
                removeEventListener(Event.ENTER_FRAME, _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(angle);
            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;
    }
    
    private function angle2Value(angle:Number):uint {
        if ( angle < 0 ) { angle += 360; }
        angle %= 360;
        var val:int;
        if (angle < 60)       { val = angle / 60; }
        else if (angle < 180) { val = 0; }
        else if (angle < 240) { val = (240 - angle) / 60; }
        else                  { val = 0; }
        trace(angle,val)
        return val;
    }
}
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;
    }
}