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: [sketchbook]で描けない図形があったので

drawRoundRect, drawRoundRectComplexに負の値を入れたときに、凹んだ形になるサンプル
/**
 * Copyright Kay ( http://wonderfl.net/user/Kay )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/nAOx
 */

// forked from Kay's [sketchbook]で描けない図形があったので
package {
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        public function FlashTest() {
            var g:GraphicsHelper = new GraphicsHelper(graphics);
            // 問題なし
            g.lineStyle(0.1,0x000000,1,true);
            g.drawRoundRect(50, 50, 200, 200, 50, 25);
            
            // drawRoundRectに負の値を入れる
            g.lineStyle(0.1,0xff0000,1,true);
            g.drawRoundRect(110, 110, 200, 200, -50, -25);

            // 問題なし
            g.lineStyle(0.1, 0x000000, 1, true);
            g.drawRoundRectComplex(170, 170, 200, 200, 50, 0, 0, 50);
            
            // drawRoundRectComplexに負の値を入れる
            g.lineStyle(0.1, 0xff0000, 1, true);
            g.drawRoundRectComplex(230, 230, 200, 200, 50, -50, -50, 50);
        }
    }
}
//package sketchbook.graphics
//{
    import flash.display.Graphics;
    import flash.geom.Point;
    import flash.geom.Matrix;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    
    /**
     * Graphicsクラスを操作する為のヘルパーオブジェクトです。
     * <p>基本的な多角形や、ポリライン描画などをサポートします</p>
     */
    /*public*/ class GraphicsHelper
    {
        protected var _target:Graphics
        
        public function GraphicsHelper(_target:Graphics)
        {
            this._target = _target
        }
        
        
        
        public function set target(val:Graphics):void
        {
            _target = val;
        }
        
        public function get target():Graphics
        {
            return _target;
        }
        
        
        /*
            Draws a series of lines to target graphics instance.
            
            points:Array array that contains Point instances
            close:Boolean if true, close line from the last point to tha first point.
        */
        public function drawLines(points:Array, close:Boolean=false):void
        {
            var g:Graphics = this._target
            
            var imax:Number = points.length
            
            g.moveTo(points[0].x, points[0].y);
            for(var i:Number=1; i<imax; i++)
                g.lineTo(points[i].x, points[i].y);
            
            if(close)
                g.lineTo(points[0].x, points[0].y);
        }
        
        
        
        /*
            Draws four points quad
            
            x0:Number
            y0:Number
            x1:Number
            y1:Number
            x2:Number
            y2:Number
        */
        public function drawQuad(x0:Number,y0:Number, x1:Number,y1:Number, x2:Number,y2:Number, x3:Number,y3:Number):void
        {
            var ar:Array = getQuadPoints(x0,y0,x1,y1,x2,y2,x3,y3);
            drawLines(ar, true);
        }
        
        
        //4点を配列化して返す
        public function getQuadPoints(x0:Number,y0:Number, x1:Number,y1:Number, x2:Number,y2:Number, x3:Number,y3:Number):Array
        {
            return [new Point(x0,y0), new Point(x1,y1), new Point(x2,y2), new Point(x3,y3)]
        }
        
        
        
        /*
            Draws three point triangle
        */
        public function drawPolygon(x0:Number,y0:Number,x1:Number,y1:Number,x2:Number,y2:Number):void
        {
            drawLines([new Point(x0,y0), new Point(x1,y1), new Point(x2,y2)], true);
        }
        
        //弧を描く
        public function drawArc(nX:Number, nY:Number, nRadius:Number, toAngle:Number, fromAngle:Number=0, closeFlg:Boolean=true):void {
            var points:Array = getArcPoints(nX,nY,nRadius,toAngle,fromAngle);
            if (closeFlg) _target.moveTo(points[0].x,points[0].y);
            var max:int = points.length-1;
            for (var i:int = 1; i < max; i+=2) {
                _target.curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
            }
        }
        public function drawArcEllipse(nX:Number, nY:Number, nWidth:Number, nHeight:Number, toAngle:Number, fromAngle:Number=0, closeFlg:Boolean=true):void {
            var nRadius:Number;
            var xRatio:Number = 1;
            var yRatio:Number = 1;
            var aWidth:Number = Math.abs(nWidth);
            var aHeight:Number = Math.abs(nHeight);
            if (aWidth < aHeight) {
                nRadius = aHeight;
                xRatio = aWidth / aHeight;
            } else {
                nRadius = aWidth;
                yRatio = aHeight / aWidth;
            }
            var points:Array = getArcPoints(0,0,nRadius,toAngle,fromAngle);
            if (closeFlg) _target.moveTo(nX+points[0].x*xRatio,nY+points[0].y*yRatio);
            var max:int = points.length-1;
            for (var i:int = 1; i < max; i+=2) {
                _target.curveTo(nX+points[i].x*xRatio,nY+points[i].y*yRatio,nX+points[i+1].x*xRatio,nY+points[i+1].y*yRatio);
            }
        }
        
        
        public function drawRing(nX:Number, nY:Number, outerRadius:Number, innerRadius:Number, toAngle:Number=360, fromAngle:Number=0):void    {
            var points:Array = getRingPoints(nX, nY, outerRadius, innerRadius, toAngle, fromAngle);
            _target.moveTo(points[0].x,points[0].y);
            var max:int = (points.length/2)-1;
            // outer
            for (var i:int = 1; i < max; i+=2) {
                _target.curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
            }
            _target.lineTo(points[max+2].x,points[max+2].y)
            // inner
            for (i = 3; i < max+1; i+=2) {
                _target.curveTo(points[max+i].x,points[max+i].y,points[max+i+1].x,points[max+i+1].y);
            }
            _target.lineTo(points[0].x, points[0].y);
        }
        
        // 円弧を描くのに必要な材料を配列として返す
        public static function getArcValue(nX:Number, nY:Number, nRadius:Number, toAngle:Number, fromAngle:Number):Array {
            var values:Array = new Array();
            var toRadian:Number   = Math.PI/180*toAngle;
            var fromRadian:Number = Math.PI/180*fromAngle;
            // 分割数を得る(45°未満:1)
            var step:int = 1;
            while (Math.abs(toRadian)/step > Math.PI/4) step++;
            // 分割された角度
            var stepRadian:Number = toRadian/step;
            // コントロールポイントまでの距離を得る
            var dist:Number = getControlRadius(nRadius,Math.abs(stepRadian));
            
            // 配列に格納
            values.toRadian = toRadian;
            values.fromRadian = fromRadian;
            values.step = step;
            values.stepRadian = stepRadian;
            values.dist = dist;
            
            return values;
        }

        public static function getArcPoints(nX:Number, nY:Number, nRadius:Number, toAngle:Number, fromAngle:Number):Array {
            var vals:Array = getArcValue(nX, nY, nRadius, toAngle, fromAngle);
            
            // コントロール/アンカーポイントを取得
            var points:Array = new Array();
            for (var i:int = 0; i <= vals.step; i++) {
                // Anchor
                points.push(new Point(nX+nRadius*Math.cos(vals.fromRadian+vals.stepRadian*i),
                                      nY+nRadius*Math.sin(vals.fromRadian+vals.stepRadian*i)));
                // Control
                points.push(new Point(nX+vals.dist*Math.cos(vals.fromRadian+vals.stepRadian*(i+0.5)),
                                      nY+vals.dist*Math.sin(vals.fromRadian+vals.stepRadian*(i+0.5))));
            }
            return points;
        }
        
        public function getRingPoints(nX:Number, nY:Number, outerRadius:Number, innerRadius:Number, toAngle:Number=360, fromAngle:Number=0):Array
        {
            var vals:Array = getArcValue(nX, nY, outerRadius, toAngle, fromAngle);
            var ratio:Number = innerRadius/outerRadius;
            var points:Array = new Array();
            var inners:Array = new Array();
            for (var i:int = 0; i <= vals.step; i++) {
                // Anchor
                var ax:Number = outerRadius*Math.cos(vals.fromRadian+vals.stepRadian*i);
                var ay:Number = outerRadius*Math.sin(vals.fromRadian+vals.stepRadian*i);
                points.push(new Point(nX+ax,       nY+ay));
                inners.push(new Point(nX+ax*ratio, nY+ay*ratio));
                // Control
                var cx:Number = vals.dist*Math.cos(vals.fromRadian+vals.stepRadian*(i+0.5));
                var cy:Number = vals.dist*Math.sin(vals.fromRadian+vals.stepRadian*(i+0.5));
                points.push(new Point(nX+cx,       nY+cy));
                inners.push(new Point(nX+cx*ratio, nY+cy*ratio));
            }
            inners.reverse();
            points = points.concat(inners);
            return points;
        }
        
        // 角度からコントロールポイントの半径を得る
        public static function getControlRadius(nRadius:Number, nRadian:Number):Number {
            var rHalf:Number = nRadian/2;
            var nHeight:Number = nRadius * Math.atan(rHalf);
            var radius:Number = Math.sqrt(Math.pow(nHeight,2)+Math.pow(nRadius,2));
            return radius;
        }
        
        //扇形、円弧と中心点を結んだ形状を描画する
        public function drawPie(x:Number, y:Number, radius:Number, degree:Number, fromDegree:Number=0, split:Number=36):void
        {
            var points:Array = getPiePoints(x, y, radius, degree, fromDegree, split)
            drawLines(points, true);
        }
        
        
        public static function getPiePoints(x:Number, y:Number, radius:Number, degree:Number, fromDegree:Number=0, split:Number=36):Array
        {
            var points:Array = getArcPoints(x, y, radius, degree, fromDegree)
            var pt:Point

            points.unshift( new Point(x, y) )
            
            return points
        }
        
        
        
        //歯車を描画する
        public function drawStar(x:Number, y:Number, outerRadius:Number, innerRadius:Number, num:Number, degreeOffset:Number=0):void
        {    
            var ar:Array = getStarPoints(x,y,outerRadius,innerRadius,num,degreeOffset);
            drawLines(ar,true);
        }
        
        //ギア状のポイント配列を取得する
        public static function getStarPoints(x:Number, y:Number, outerRadius:Number, innerRadius:Number, num:Number, degreeOffset:Number=0):Array
        {
            var points:Array = new Array();
            var drad:Number = Math.PI * 2 / num
            var xOffset:Number = x
            var yOffset:Number = y
            var radOffset:Number = degreeOffset * Math.PI / 180
            
            var imax:Number = num

            for(var i:Number=0; i<imax; i++)
            {
                var rad:Number = Math.PI * 2 * i/ num + radOffset
                var rad2:Number = Math.PI * 2 * (i+0.5)/ num  + radOffset
                
                var pt:Point 
                pt = new Point()
                pt.x = Math.cos(rad)*outerRadius + xOffset
                pt.y = Math.sin(rad)*outerRadius + yOffset
                points.push(pt);
            
                pt = new Point()
                pt.x = Math.cos(rad2)*innerRadius + xOffset
                pt.y = Math.sin(rad2)*innerRadius + yOffset
                points.push(pt);
            }
            return points
        }
        
        
        
        
        
        /*
        ---------------------------------------------------------------------------------------------
        Begin Fill等へのアクセス関数
        本来のgraphicsにそのまま委譲します
        ---------------------------------------------------------------------------------------------
        */
        
        public function beginFill(color:uint, alpha:Number=1.0):void
        {
            _target.beginFill(color,alpha)
        }
        
        public function clear():void
        {
            _target.clear()
        }
        
        public function curveTo(controlX:Number, controlY:Number, anchorX:Number, anchorY:Number):void
        {
            _target.curveTo(controlX, controlY, anchorX, anchorY)
        }
        
        public function drawRect(x:Number, y:Number, width:Number, height:Number):void{
            _target.drawRect(x,y,width,height)
        }
        
        public function drawCircle(x:Number, y:Number, radius:Number):void
        {
            _target.drawCircle(x,y,radius)
        }
        
        public function drawEllipse(x:Number, y:Number, width:Number, height:Number):void
        {
            _target.drawEllipse(x,y,width,height)
        }
        
        public function drawRoundRect(x:Number,y:Number,width:Number,height:Number,ellipseWidth:Number=0,ellipseHeight:Number=0):void
        {
            // 入力値を補正
            if (ellipseHeight == 0) ellipseHeight = ellipseWidth;
            if (ellipseWidth * ellipseHeight < 0) ellipseHeight*=-1;
            
            if (ellipseWidth >= 0) {
                _target.drawRoundRect(x,y,width,height,ellipseWidth,ellipseHeight);
            } else {
                _target.moveTo(x-ellipseWidth, y);
                _target.lineTo(x+width+ellipseWidth,y);
                drawArcEllipse(x+width, y, ellipseWidth, ellipseHeight, -90, 180, false);
                _target.lineTo(x+width, y+height+ellipseHeight);
                drawArcEllipse(x+width, y+height, ellipseWidth, ellipseHeight, -90, 270, false);
                _target.lineTo(x-ellipseWidth, y+height);
                drawArcEllipse(x, y+height, ellipseWidth, ellipseHeight, -90, 0);
                _target.lineTo(x, y-ellipseHeight);
                drawArcEllipse(x, y, ellipseWidth, ellipseHeight, -90, 90, false);
            }
        }
        
        public function drawRoundRectComplex(x:Number,y:Number,width:Number,height:Number, topLeftRadius:Number, topRightRadius:Number, bottomLeftRadius:Number, bottomRightRadius:Number):void
        {
            if (topLeftRadius > 0) {
                _target.moveTo(x+topLeftRadius, y);
            } else if (topLeftRadius < 0) {
                _target.moveTo(x-topLeftRadius, y);
            } else {
                _target.moveTo(x, y);
            }

            if (topRightRadius > 0) {
                _target.lineTo(x+width-topRightRadius,y);
                drawArc(x+width-topRightRadius, y+topRightRadius, topRightRadius, 90, 270, false);
            } else if (topRightRadius < 0) {
                _target.lineTo(x+width+topRightRadius,y);
                drawArc(x+width, y, -topRightRadius, -90, 180, false);
            } else {
                _target.lineTo(x+width,y);
            }
            if (bottomRightRadius > 0) {
                _target.lineTo(x+width, y+height-bottomRightRadius);
                drawArc(x+width-bottomRightRadius, y+height-bottomRightRadius, bottomRightRadius, 90, 0, false);
            } else if (bottomRightRadius < 0) {
                _target.lineTo(x+width, y+height+bottomRightRadius);
                drawArc(x+width, y+height, -bottomRightRadius, -90, 270, false);
            } else {
                _target.lineTo(x+width,y+height);
            }
            if (bottomLeftRadius > 0) {
                _target.lineTo(x+bottomLeftRadius, y+height);
                drawArc(x+bottomLeftRadius, y+height-bottomLeftRadius, bottomLeftRadius, 90, 90, false);
            } else if (bottomLeftRadius < 0) {
                _target.lineTo(x-bottomLeftRadius, y+height);
                drawArc(x, y+height, -bottomLeftRadius, -90, 0);
            } else {
                _target.lineTo(x,y+height);
            }
            if (topLeftRadius > 0) {
                _target.lineTo(x, y+topLeftRadius);
                drawArc(x+topLeftRadius, y+topLeftRadius, topLeftRadius, 90, 180, false);
            } else if (topLeftRadius < 0) {
                _target.lineTo(x, y-topLeftRadius);
                drawArc(x, y, -topLeftRadius, -90, 90, false);
            } else {
                _target.lineTo(x,y);
            }
        }
        
        
        public function endFill():void
        {
            _target.endFill()
        }
        
        public function moveTo(x:Number, y:Number):void
        {
            _target.moveTo(x,y)
        }
        
        public function lineTo(x:Number, y:Number):void
        {
            _target.lineTo(x,y)
        }
        
        public function lineStyle(thickness:Number=0,
            color:uint=0,alpha:Number=1,
            pixelHinting:Boolean=false,
            scaleMode:String = "normal",
            caps:String=null,
            joints:String=null,
            miterLimit:Number=3):void
        {
            _target.lineStyle(thickness, color, alpha, pixelHinting, scaleMode, caps, joints, miterLimit)
        }
        
        public function beginBitmapFill(bitmap:BitmapData,matrix:Matrix=null,repeat:Boolean=true,smooth:Boolean=false):void
        {
            _target.beginBitmapFill(bitmap,matrix,repeat,smooth)
        }
        
        public function beginGradientFill(type:String, color:Array, alphas:Array, ratios:Array, matrix:Matrix=null, spreadMethod:String="pad", interpolationMethod:String="rgb",focalPointRation:Number=0.0):void
        {
            _target.beginGradientFill(type, color, alphas, ratios, matrix, spreadMethod, interpolationMethod,focalPointRation)
        }
        
        public function lineGradientStyle( type:String,colors:Array,alphas:Array,ratios:Array,matrix:Matrix=null,spreadMethod:String="pad",interpolationMethod:String="rgb",focalPointRatio:Number  = 0.0):void
        {
            _target.lineGradientStyle(type,colors,alphas,ratios,matrix,spreadMethod,interpolationMethod,focalPointRatio)
        }
    }
//}