我正在尝试进行循环进度条,但我被卡住了。
绘制彩色圆圈时没有任何问题,但我不知道如何删除中心的颜色以及如何删除代表缺失百分比的小部分。
实际的解决方案是在背景中使用我替换每个5%的图像。它有效,但它很沉重,如果我需要改变圆圈的颜色,我必须重新绘制所有20张图片。
有什么解决方案可以让我动态地绘制这个“进步圈”吗?
答案 0 :(得分:3)
这比我想象的要复杂得多。
您需要使用alpha蒙版在圆圈上打孔。这很难理解,因为关于如何正确地完成它的文档非常少,但是一旦你搞清楚它就相对容易了。您需要使用Group
“图层”创建blendMode
并将cacheAsBitmap
设置为true。然后,使用Ellipse
创建形状并创建一个组(必须位于其下方),其中blendMode
为“erase”,cacheAsBitmap设置为true。在该组中,绘制您希望用于在父形状中打孔的形状。
示例:
<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>
要做实际进度,你需要做一点触发。不幸的是,没有办法(我知道)没有bezier路径这样做。因此,您基本上创建了一个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之间的数字。请确保将其限制在该范围内。如果我没记错的话,如果它超出了这些界限就会中断。
希望这会有所帮助。再一次,我无法向你展示更多,但它应该足以让你开始
答案 1 :(得分: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>
谢谢你们的帮助