Drawing curved lines and arrows in Flex
While working on one of my mapping projects, I needed to draw some arrows between different points on the map. After searching the web I found something close to what I was looking for, but I wanted curved arrows for a slick look.
If you haven’t already, you should read up on the features provided by the Flex 3 drawing API. Most components in Flex have a graphics layer(i.e. Canvas.graphics) on which you can draw lines and shapes. Drawing a simple line goes as follows:
var origin:Point = new Point(0,0); var destination:Point = new Point(lineLength,lineHeight); var lineThickness:Number = 2; var lineColor:Number = 0x000000; var lineAlpha:Number = 1; graphics.clear(); graphics.lineStyle(lineThickness,lineColor,lineAlpha); graphics.moveTo(origin.x,origin.y); graphics.lineTo(destination.x,destination.y);
Drawing a curved line can be acomplished by supplying a control point that the curve must pass through on its way to the destination. I used simple vector geometry to calculate the control point in this example:
var origin:Point = new Point(0,0);
var destination:Point = new Point(lineLength,lineHeight);
// start curve anchor at halfway point between origin and destination
var curveAnchor:Point = new Point(
(origin.x + destination.x)/2,
(origin.y + destination.y)/2);
// shift point perpendicular to line that is curvePercent of original line
if (origin.x > destination.x)
{
curveAnchor.x -= (destination.y-origin.y) * curvePercent;
curveAnchor.y += (destination.x-origin.x) * curvePercent;
}
else
{
curveAnchor.x += (destination.y-origin.y) * curvePercent;
curveAnchor.y -= (destination.x-origin.x) * curvePercent;
}
var lineThickness:Number = 2;
var lineColor:Number = 0x000000;
var lineAlpha:Number = 1;
graphics.clear();
graphics.lineStyle(lineThickness,lineColor,lineAlpha);
graphics.moveTo(origin.x,origin.y);
graphics.curveTo(curveAnchor.x,curveAnchor.y,destination.x,destination.y);
Noel Billig of dncompute.com created a great API for drawing arrows at the end of lines. Utilizing his API we can quickly create a straight line with an arrow at the end:
var origin:Point = new Point(0,0);
var destination:Point = new Point(lineLength,lineHeight);
var lineThickness:Number = 2;
var lineColor:Number = 0x000000;
var lineAlpha:Number = 1;
graphics.clear();
graphics.beginFill(lineColor,lineAlpha);
GraphicsUtil.drawArrow(graphics,origin,destination,
{shaftThickness:lineThickness,headWidth:10,headLength:15,
shaftPosition:.20,edgeControlPosition:.5
}
);
Starting with Noel’s code, I made some enhancements so I could draw a curved arrow instead of just a straight one. It took quite a bit of tinkering but I eventually found a solution that works great. The syntax is similar to above but now we pass in the control point also:
GraphicsUtil.drawArrow(graphics,origin,destination,curveAnchor,
{shaftThickness:lineThickness,headWidth:10,headLength:15,
shaftPosition:.20,edgeControlPosition:.5
}
);
Check out the demo below which outlines each of these examples. Right-click to view source.