flash as3 нарисуйте пончик-клин (дуга с внутренним и внешним радиусом) с помощью кривой - PullRequest
3 голосов
/ 28 ноября 2011

Я пытаюсь нарисовать дугу во флеше, используя минимальное количество кода / итераций. Я перенес этот метод ниже из старого примера AS2, но он требует цикла через несколько шагов, чтобы он выглядел гладко, и я бы предпочел этого избежать. Я видел, что AS3 имеет команду "curveTo", но на самом деле она не рисует круговую дугу, она рисует кривую Безье. Есть ли команда дуги во вспышке? или способ нарисовать отрезок круга?

Вот мой старый код:

function drawSolidArc (drawObj:Object, centerX:Number,centerY:Number,innerRadius:Number,outerRadius:Number,startAngle:Number,arcAngle:Number,steps:int=20):void {
    if (Math.abs(startAngle)>360)startAngle%=360
    if (Math.abs(arcAngle)>360)arcAngle%=360
    startAngle/=360,arcAngle/=360
    var twoPI:Number = 2 * Math.PI;
    var angleStep:Number = arcAngle/steps;
    var angle:Number, i:int, endAngle:Number;
    var xx:Number = centerX + Math.cos(startAngle * twoPI) * innerRadius;
    var yy:Number = centerY + Math.sin(startAngle * twoPI) * innerRadius;
    var xxInit:Number=xx;
    var yyInit:Number=yy;
    drawObj.graphics.moveTo(xx,yy);
    for(i=1; i<=steps; i++) {
        angle = (startAngle + i * angleStep) * twoPI;
        xx = centerX + Math.cos(angle) * innerRadius;
        yy = centerY + Math.sin(angle) * innerRadius;
        drawObj.graphics.lineTo(xx,yy);
    }
    endAngle = startAngle + arcAngle;
    for(i=0;i<=steps;i++) {
        angle = (endAngle - i * angleStep) * twoPI;
        xx = centerX + Math.cos(angle) * outerRadius;
        yy = centerY + Math.sin(angle) * outerRadius;
        drawObj.graphics.lineTo(xx,yy);
    }

    drawObj.graphics.lineTo(xxInit,yyInit);
};

var myArc:Shape = new Shape(); //or another DisplayObject

myArc.graphics.beginFill(0xcccccc, 0.50);
//objName, centerX,centerY, innerRadius, outerRadius, startAngle (12 o'clock is -90), arcAngle (degrees from startAngle), steps (smoothness)
drawSolidArc (myArc,250, 250, 180, 200, -90, 65, 100);
myArc.graphics.endFill();
this.addChild(myArc);

Ответы [ 5 ]

1 голос
/ 28 ноября 2011

Я сделал что-то похожее на решение Джереми, хотя я этого не скрывал.Очевидно, что если вы создадите еще одну дугу меньшего радиуса из той же центральной точки, она будет вычтена из существующей фигуры, поэтому я просто сделал еще один вызов drawSolidArc после первого и перед endFill, с нулем в качестве центральной точки и внешним радиусомявляющийся желаемым внутренним радиусом первого клина:

var myArc:Sprite = new Sprite();
myArc.graphics.beginFill(0xcccccc, 1);
drawArc(myArc, 275, 200, 60, 150, 35); //spriteName, startX, startY, innerRadius, radius, arcAngle, startAngle
drawArc(myArc, 275, 200, 0, 60, 35); //subtract out the middle by drawing a new circle over the top of it
myArc.graphics.endFill();
this.addChild(myArc);
1 голос
/ 28 ноября 2011

Ниже приведена ссылка на несколько разных классов рисования фигур, которые я написал.Вы можете достичь желаемого отрезка круга, нарисовав клин и замаскировав его центр второй формой окружности.

https://github.com/makemachine/makemachine.actionscript/tree/master/src/makemachine/display/shapes

1 голос
/ 28 ноября 2011

Вот как я это сделал:

Нарисуйте пончик и замаскируйте его:

_foreground = new Sprite();
_foreground.graphics.beginFill(_colour)
_foreground.graphics.drawCircle(0, 0, _outerRadius);
_foreground.graphics.drawCircle(0, 0, _innerRadius);
_foreground.graphics.endFill();
_container.addChild(_foreground);

_mask = new Sprite();
_mask.graphics.beginFill(0xff0000);
_foreground.mask = _mask;

Затем нарисуйте его, используя этот метод - вписав клин в маску

private function draw(e:Event):void //Called each frame (if animating)
{
// No need to draw more than 360
if (Math.abs(_arc) > _endAngle) 
{
    _arc = _endAngle;
    stop();
}

_numOfSegs = Math.ceil(Math.abs(_arc) / 45);
_segAngle = _arc / _numOfSegs;
_segAngle = (_segAngle / 180) * Math.PI;
_angle = (_startAngle / 180) * Math.PI;

// Calculate the start point
_ax = Math.cos(_angle) * _outerRadius;
_ay = Math.sin(-_angle) * _outerRadius;

// Draw the first line
_mask.graphics.lineTo(_ax, _ay);

for (var i:int=0; i<_numOfSegs; i++) 
{
    _angle += _segAngle;
    _angleMid = _angle - (_segAngle / 2);
    _bx = Math.cos(_angle) * _outerRadius;
    _by = Math.sin(_angle) * _outerRadius;
    _cx = Math.cos(_angleMid) * (_outerRadius / Math.cos(_segAngle / 2));
    _cy = Math.sin(_angleMid) * (_outerRadius / Math.cos(_segAngle / 2));
    _mask.graphics.curveTo(_cx, _cy, _bx, _by);
}

// Close the wedge
_mask.graphics.lineTo(0, 0);
_arc += 3.6; //This gives a 100 steps to complete the circle
}
1 голос
/ 28 ноября 2011

Graphics.cubicCurveTo () даст вам лучшее приближение дуги, чем curveTo.Но это все еще не идеально.

0 голосов
/ 28 ноября 2011

Тогда есть эта реализация . Но это почти так же грязно, как то, что вы опубликовали. Боюсь, что нет элегантного способа (несколько линий или около того) нарисовать дугу.

...