Flex编程皮肤: (4)绘制圆角矩形的工具类GraphicsUtil
编程皮肤的基类mx.skins.ProgrammaticSkin使用了工具类mx.utils.GraphicsUtil,用来绘制圆角矩形。我们看看该工具类做了些什么事情。
test.as
package { import flash.display.Graphics; import flash.display.Sprite; import utils.GraphicsUtil; public class test extends Sprite { public function test() { super(); var g:Graphics = this.graphics; g.beginFill(0x000000,1); g.lineStyle(3,0x000000,1); //使用绘制圆角矩形的工具类 GraphicsUtil.drawRoundRectComplex(g, 50,50,400,200, 10,5,20,40); g.endFill(); } } }
GraphicsUtilGraphicsUtil.as
该类的内容完全复制了Flex框架中的mx.utils.GraphicsUtil类。
可以看到该类主要就是计算四个圆角的二次贝塞尔曲线需要的控制点坐标。
而绘制二次贝塞尔曲线是ActionScript提供的基本绘图功能之一。
Flex框架对每个圆角都绘制了两个曲线,来组合成一个圆角。其间使用的系数(如0.292893218813453)应该是反复试验得到的最佳值。
这涉及到几何和数学,我还是避而远之不去分析为妙。
package utils { import flash.display.Graphics; public class GraphicsUtil { public static function drawRoundRectComplex(graphics:Graphics, x:Number, y:Number, width:Number, height:Number, topLeftRadius:Number, topRightRadius:Number, bottomLeftRadius:Number, bottomRightRadius:Number):void { var xw:Number = x + width; var yh:Number = y + height; var minSize:Number = width < height ? width * 2 : height * 2; topLeftRadius = topLeftRadius < minSize ? topLeftRadius : minSize; topRightRadius = topRightRadius < minSize ? topRightRadius : minSize; bottomLeftRadius = bottomLeftRadius < minSize ? bottomLeftRadius : minSize; bottomRightRadius = bottomRightRadius < minSize ? bottomRightRadius : minSize; // bottom-right corner var a:Number = bottomRightRadius * 0.292893218813453; // radius - anchor pt; var s:Number = bottomRightRadius * 0.585786437626905; // radius - control pt; graphics.moveTo(xw, yh - bottomRightRadius); graphics.curveTo(xw, yh - s, xw - a, yh - a); graphics.curveTo(xw - s, yh, xw - bottomRightRadius, yh); // bottom-left corner a = bottomLeftRadius * 0.292893218813453; s = bottomLeftRadius * 0.585786437626905; graphics.lineTo(x + bottomLeftRadius, yh); graphics.curveTo(x + s, yh, x + a, yh - a); graphics.curveTo(x, yh - s, x, yh - bottomLeftRadius); // top-left corner a = topLeftRadius * 0.292893218813453; s = topLeftRadius * 0.585786437626905; graphics.lineTo(x, y + topLeftRadius); graphics.curveTo(x, y + s, x + a, y + a); graphics.curveTo(x + s, y, x + topLeftRadius, y); // top-right corner a = topRightRadius * 0.292893218813453; s = topRightRadius * 0.585786437626905; graphics.lineTo(xw - topRightRadius, y); graphics.curveTo(xw - s, y, xw - a, y + a); graphics.curveTo(xw, y + s, xw, y + topRightRadius); graphics.lineTo(xw, yh - bottomRightRadius); } } }效果图: