0

我正在尝试做一个圆形进度条,但我被卡住了。

我在绘制彩色圆圈时没有任何问题,但我不知道如何去除中心的颜色以及如何去除代表缺失百分比的小部分。

实际的解决方案是在背景中使用一个图像,我每替换 5%。它可以工作,但它又重又生涩,如果我需要更改圆圈的颜色,我必须重新绘制所有 20 张图片。

有什么解决方案可以让我动态地绘制这个“进度圈”吗?

4

2 回答 2

3

这比我认为你意识到的要复杂得多。

您需要使用 alpha 蒙版在圆圈上打一个洞。这很难弄清楚,因为关于如何正确执行此操作的文档很少,但一旦弄清楚就相对容易。您需要创建一个GroupblendMode层”并设置cacheAsBitmap为true。然后,您使用“擦除”和 cacheAsBitmap 设置为 true创建您的形状Ellipse并创建一个组(必须在其下方) 。blendMode在该组中,您绘制要用于在父形状中打孔的形状。

例子:

<s:Group cacheAsBitmap="true" blendMode="layer">
    <s:Ellipse id="background" width="84" height="84" >
        <s:fill>
            <s:SolidColor color="0"/>
        </s:fill>
    </s:Ellipse>

    <s:Group id="backgroundMask" horizontalCenter="0" verticalCenter="0" blendMode="erase" cacheAsBitmap="true">
        <s:Ellipse width="64" height="64" >
            <s:fill>
                <s:SolidColor color="0"/>
            </s:fill>
        </s:Ellipse>
    </s:Group>
</s:Group>

这直接取自我最近构建的应用程序,因此我可以验证它是否有效。这将创建一个直径为 84px 的圆,中心有一个 64px 的孔。

编辑:正如 RIAStar 在评论中指出的那样,你实际上可以用笔画而不是我复杂的方式来做到这一点。

从他的评论中:

<s:Ellipse width="74" height="74">
    <s:stroke>
    <s:SolidColorStroke weight="10"/>
    </s:stroke>
</s:Ellipse>

要进行实际进度,您需要进行一些触发。不幸的是,没有贝塞尔路径就没有办法(据我所知)。因此,您基本上创建了一个Path对象并在进度更新时重绘其data. 这将是实际圆圈的掩码。

你也需要根据象限来绘制它,所以它更加复杂。基本上,您从顶部中间开始,向下绘制到圆心,绘制到进度中的当前点,然后绘制到该象限的角落,然后绘制到之前的每个角落,最后回到顶部中间。

我无法给出绘制实际路径的代码(它不是可以在任何地方找到的通用代码,而且我的 NDA 阻止我这样做),但我可以向您展示如何获得当前进度的圆圈上的点。您可能需要根据圈子的属性来填充该点,但无论如何,这应该是一个很好的起点。

var halfHeight:Number = this.background.height / 2;
var halfWidth:Number = this.background.width / 2;
var angle:Number = -this.progress * 2 * Math.PI - Math.PI / 2; (uses negative progress to indicate counter-clockwise direction)
var pointOnCircle:Point = new Point(halfWidth * Math.cos( angle ) + halfWidth, halfWidth * Math.sin( angle ) + halfWidth);

应该正好位于上面绘制的圆圈的pointOnCircle外边缘。this.progress是一个介于 0 和 1 之间的数字。确保将其限制在该范围内。如果我没记错的话,如果超出了这些界限,就会中断。

希望这会有所帮助。再说一次,我真的不能向你展示更多的东西,但它应该足以让你开始

于 2013-10-02T18:15:54.727 回答
1

谢谢你们。

最后,我有来自http://flassari.is/2009/11/pie-mask-in-as3/的 Josh 的代码和脚本

我使用了来自 flassari 的代码来绘制和更新圆(编辑以在恢复模式下进行,从 100% 到 0%),以及 Josh 在圆心打洞的方法。

这是我使用的主要代码:

private function init():void
{
    // Store sprites
    var container:UIComponent = new UIComponent();
    gr.addElementAt(container, 0);

    // Draw the full circle with colors
    circleToMask.graphics.beginGradientFill(GradientType.RADIAL, [0x000000, 0x000000], [0, 1], [80, 130]);
    circleToMask.graphics.drawCircle(0, 0, 50);
    circleToMask.graphics.endFill();

    // Add the circle
    container.addChildAt(circleToMask, 0);

    // Add the mask
    container.addChild(circleMask);

    Set the position of the circle
    circleToMask.x = (circleMask.x = 14);
    circleToMask.y = (circleMask.y = 14);
    circleToMask.mask = circleMask;

    // Draw the circle at 100%
    renderChart(1);
}
private function renderChart(percentage:Number):void
{
    circleMask.graphics.clear();
    circleMask.graphics.beginFill(0);

    // Draw the circle at the given percentage            /------ set the begin at the middle top
    drawPieMask(circleMask.graphics, percentage, 100, -1.57, 8);
    circleMask.graphics.endFill();
}

// Function from flassari (a little simplified)
private function drawPieMask(graphics:Graphics, percentage:Number, radius:Number = 50, rotation:Number = 0, sides:int = 6):void {
    radius /= Math.cos(1/sides * Math.PI);
    var lineToRadians:Function = function(rads:Number):void {
        graphics.lineTo(Math.cos(rads) * radius + x, Math.sin(rads) * radius + y);
    };
    var sidesToDraw:int = Math.floor(percentage * sides);
    for (var i:int = 0; i <= sidesToDraw; i++)
        lineToRadians((i / sides) * (Math.PI * 2) + rotation);
    if (percentage * sides != sidesToDraw)
        lineToRadians(percentage * (Math.PI * 2) + rotation);
}

在这里,mxml:

<s:Group verticalCenter="0" horizontalCenter="0">
    <s:Rect width="100%" height="100%">
        <s:fill>
            <s:SolidColor color="0xcccccc"/>
        </s:fill>
    </s:Rect>
    <s:Label id="lab" verticalCenter="0" horizontalCenter="0" text="test"/>
    <s:Group id="gr" cacheAsBitmap="true" blendMode="layer" verticalCenter="0" horizontalCenter="0">
        <s:Group verticalCenter="0" horizontalCenter="0" blendMode="erase" cacheAsBitmap="true">
            <s:Ellipse width="30" height="30">
                <s:fill>
                    <s:SolidColor color="0"/>
                </s:fill>
            </s:Ellipse>
        </s:Group>
    </s:Group>
</s:Group>

谢谢你们的帮助

于 2013-10-03T09:24:55.693 回答