// graphics, vector of xy coords, closed boolean
function bezierSkin(g:Graphics, bez:Vector.<Number>, closed:Boolean = true):void {
var avg:Vector.<Number> = calcAvgs(bez);
var i:int, n:int;
var leng:int = bez.length;
if (closed){
g.moveTo(avg[0], avg[1]);
for (i = 2; i < leng; i+=2) {
n=i+1;
g.curveTo(bez[i], bez[n], avg[i], avg[n]);
}
g.curveTo(bez[0], bez[1], avg[0], avg[1]);
}else{
g.moveTo(bez[0], bez[1]);
g.lineTo(avg[0], avg[1]);
for (i = 2; i < leng-2; i+=2) {
n=i+1;
g.curveTo(bez[i], bez[n], avg[i], avg[n]);
}
g.lineTo(bez[ leng - 2], bez[ leng - 1]);
}
}
// create anchor points by averaging the control points
function calcAvgs(v:Vector.<Number>):Vector.<Number> {
var avg:Vector.<Number> = new Vector.<Number>();
var leng:int=v.length;
for (var i:int = 2; i<leng; i+=1) {
var prev:Number=i-2;
avg.push( (v[prev] + v[i]) / 2 );
}
// close
avg.push( (v[0] + v[ leng - 2]) / 2 );
avg.push( (v[1] + v[ leng - 1]) / 2 );
return avg;
}
// test out the functions:
graphics.lineStyle(0,0x000000);
// draw a very rounded rect
bezierSkin(graphics, Vector.<Number>([100,100,200,100,200,200,100,200]) );
// draw a random curve with 10 xy coords
var rnd:Vector.<Number> = new Vector.<Number>();
for (var i:int = 0; i<20; i++) rnd.push(Math.random()*100);
bezierSkin(graphics, rnd);
// erase everything and allow the used to draw a smooth curve with the mouse
stage.addEventListener(MouseEvent.MOUSE_DOWN, onLoop);
var index:int = 0;
var pnts:Vector.<Number> = new Vector.<Number>();
function onLoop(evt:MouseEvent):void {
pnts.push(mouseX);
pnts.push(mouseY);
graphics.clear();
graphics.lineStyle(0,0x000000);
// draw a smooth curved line
bezierSkin(graphics,pnts,false);
}
The above code uses averaging to generate anchor points for curveTo() calls. This is an easy way to always draw smooth curves.
This is an old one that I’ve seen floating around since the drawing api first came out… but I it’s an important snippet, so I figured I’d post it.