0

I have a bar chart whose columns I'd like to apply a linear gradient fill to via the setStyle method. In the method I'm using to configure the colors, the following code sets the gradient:

public function configureColor(series:Series):void {
    var lg:LinearGradient = GradientUtil.getLinearGradient([color1, color2], 0.8, 45);
    series.setStyle("fill", lg);
  ...
}

The getLinearGradient method:

public function getLinearGradient(colors:Array, alpha:Number, angle:Number = 0.0):LinearGradient {
    var lg:LinearGradient = new LinearGradient();
    lg.angle = angle;
    var entries:Array = []
    for each (var color:uint in colors) {
        entries.push(new GradientEntry(color, NaN, alpha));
    }
    lg.entries = entries;
    return lg;
}

For some reason, the gradients that I get on the columns are "choppy". The transition from one color to the next occurs in a very small section of the column, rather than a smooth transition from the top to the bottom of the bar. How can I get it so that it does end up being a smooth transition?

Edit: Example of what the issue I'm having looks like enter image description here

4

1 に答える 1

0

これはLinearGradientクラスの問題のようです。私の最初の仮定はBoxItemRenderer、チャートに塗りつぶしを描くのはそれであるということでした。begin()しかし、そこを見ると、レンダラーが塗りつぶしを開始するために使用するグラデーションの方法がわかりました。

問題はおそらく特殊なケースであり、幅と高さの比率が大きい長方形で90度以外の角度を使用すると顕著になります。この問題は、単純なrectで再現できます。

<s:Rect width="200" height="40">
    <s:fill>
        <s:LinearGradient rotation="45">
            <s:GradientEntry color="#ff0000"/>
            <s:GradientEntry color="#0000ff"/>
        </s:LinearGradient>
    </s:fill>
</s:Rect>

私のハッキーな解決策は、そのメソッドを拡張LinearGradientしてオーバーライドすることでした。begin()元のコードをコピーし、幅が間違っていると判断した数行をコメントアウトしました。さまざまな角度でテストしましたが、問題ないようです。

確かに、コメントした行の目的がわかりません。おそらく、有効なユースケースがあります。

package
{
    import flash.display.GradientType;
    import flash.display.Graphics;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    import mx.core.mx_internal;
    import mx.graphics.LinearGradient;

    use namespace mx_internal;

    public class CustomGradient extends LinearGradient
    {
        private static var commonMatrix:Matrix = new Matrix();

        public function CustomGradient()
        {
            super();
        }

        override public function begin(target:Graphics, targetBounds:Rectangle, targetOrigin:Point):void
        {
            commonMatrix.identity();

            if (!compoundTransform)
            {
                var tx:Number = x;
                var ty:Number = y;
                var length:Number = scaleX;

                if (isNaN(length))
                {
                    // Figure out the two sides
                    if (rotation % 90 != 0)
                    {           
//                      // Normalize angles with absolute value > 360 
//                      var normalizedAngle:Number = rotation % 360;
//                      // Normalize negative angles
//                      if (normalizedAngle < 0)
//                          normalizedAngle += 360;
//                      
//                      // Angles wrap at 180
//                      normalizedAngle %= 180;
//                      
//                      // Angles > 90 get mirrored
//                      if (normalizedAngle > 90)
//                          normalizedAngle = 180 - normalizedAngle;
//                      
//                      var side:Number = targetBounds.width;
//                      // Get the hypotenuse of the largest triangle that can fit in the bounds
//                      var hypotenuse:Number = Math.sqrt(targetBounds.width * targetBounds.width + targetBounds.height * targetBounds.height);
//                      // Get the angle of that largest triangle
//                      var hypotenuseAngle:Number =  Math.acos(targetBounds.width / hypotenuse) * 180 / Math.PI;
//                      
//                      // If the angle is larger than the hypotenuse angle, then use the height 
//                      // as the adjacent side of the triangle
//                      if (normalizedAngle > hypotenuseAngle)
//                      {
//                          normalizedAngle = 90 - normalizedAngle;
//                          side = targetBounds.height;
//                      }
//                      
//                      // Solve for the hypotenuse given an adjacent side and an angle. 
//                      length = side / Math.cos(normalizedAngle / 180 * Math.PI);
                        length=Math.max(targetBounds.width, targetBounds.height);
                    }
                    else 
                    {
                        // Use either width or height based on the rotation
                        length = (rotation % 180) == 0 ? targetBounds.width : targetBounds.height;
                    }
                }

                // If only x or y is defined, force the other to be set to 0
                if (!isNaN(tx) && isNaN(ty))
                    ty = 0;
                else if (isNaN(tx) && !isNaN(ty))
                    tx = 0;

                // If x and y are specified, then move the gradient so that the
                // top left corner is at 0,0
                if (!isNaN(tx) && !isNaN(ty))
                    commonMatrix.translate(GRADIENT_DIMENSION / 2, GRADIENT_DIMENSION / 2); // 1638.4 / 2

                // Force the length to a absolute minimum of 2. Values of 0, 1, or -1 have undesired behavior   
                if (length >= 0 && length < 2)
                    length = 2;
                else if (length < 0 && length > -2)
                    length = -2;

                // Scale the gradient in the x direction. The natural size is 1638.4px. No need
                // to scale the y direction because it is infinite
                commonMatrix.scale (length / GRADIENT_DIMENSION, 1 / GRADIENT_DIMENSION);

                commonMatrix.rotate (!isNaN(_angle) ? _angle : rotationInRadians);
                if (isNaN(tx))
                    tx = targetBounds.left + targetBounds.width / 2;
                else
                    tx += targetOrigin.x;
                if (isNaN(ty))
                    ty = targetBounds.top + targetBounds.height / 2;
                else
                    ty += targetOrigin.y;
                commonMatrix.translate(tx, ty); 
            }
            else
            {
                commonMatrix.translate(GRADIENT_DIMENSION / 2, GRADIENT_DIMENSION / 2);
                commonMatrix.scale(1 / GRADIENT_DIMENSION, 1 / GRADIENT_DIMENSION);
                commonMatrix.concat(compoundTransform.matrix);
                commonMatrix.translate(targetOrigin.x, targetOrigin.y);
            }            

            target.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios,
                commonMatrix, spreadMethod, interpolationMethod);   
        }
    }
}

[編集] ifステートメント全体をコメントアウトし、length代わりに最大ディメンションを使用します。if (normalizedAngle > hypotenuseAngle)元のハックは条項をコメントアウトしただけです。おそらくまだバグがありますが、両方の問題のケースに対処します。

于 2012-08-15T22:21:11.407 に答える