/**
* Copyright grapefrukt ( http://wonderfl.net/user/grapefrukt )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4qXM
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* ...
* @author Martin Jonasson (m@grapefrukt.com)
*/
public class Main extends Sprite {
static private const LINE_WIDTH :Number = 20;
private var _animation_offset :int = 0;
private var _nodes :Vector.<Point>;
public function Main():void {
// create a list with a bunch of points
_nodes = new Vector.<Point>();
for (var i:int = 0; i < 20; i++) _nodes.push(new Point);
addEventListener(Event.ENTER_FRAME, handleEnterFrame)
}
private function handleEnterFrame(e:Event):void {
var i:int = 0;
// step the animation forward
_animation_offset += 4;
// move the nodes
for (i = 0; i < _nodes.length; i++) {
_nodes[i].x = 50 + 20 * (i);
_nodes[i].y = 250 + Math.sin((_animation_offset + i * 40) / 100) * 150;
}
// two lists for coordinates, one for each side of the line
var coords1:Vector.<Point> = new Vector.<Point>();
var coords2:Vector.<Point> = new Vector.<Point>();
// step over all coords in the list
for (i = 0; i < _nodes.length; i++) {
// calculate the position relative to the previous segment
var angle_prev:Point = new Point;
if (i > 0) {
angle_prev.x = _nodes[i - 1].x - _nodes[i].x;
angle_prev.y = _nodes[i - 1].y - _nodes[i].y;
// if this is the first segment we use the angle to the next segment instead
} else {
angle_prev.x = _nodes[i].x - _nodes[i + 1].x;
angle_prev.y = _nodes[i].y - _nodes[i + 1].y;
}
// and again the relative position compared to the next segment
var angle_next:Point = new Point;
if (i < _nodes.length - 1) {
angle_next.x = _nodes[i + 1].x - _nodes[i].x;
angle_next.y = _nodes[i + 1].y - _nodes[i].y;
// if this is the last segment we look back at the previous segment instead
// this and the previous else-block could be skipped since they will give the same
// results for both angle_next and angle_prev, but i'm keeping them to make the later
// parts of the function simpler
} else {
angle_next.x = _nodes[i].x - _nodes[i - 1].x;
angle_next.y = _nodes[i].y - _nodes[i - 1].y;
}
// then we normalize the points to a lenght of one, since we only
// really care about the angle not the distance.
angle_prev.normalize(1);
angle_next.normalize(1);
// now we use the current node's position as a starting
// point adding in the average of the two angle offsets
// we calculated. by inverting and swapping the x/y
// values we rotate the angle by 90 degrees to get a line
// that extends from the side of the line instead of alongside it.
// we multiply that vector by the desired line width
var p1:Point = new Point;
p1.x = _nodes[i].x + ((-angle_next.y+angle_prev.y) / 2) * LINE_WIDTH;
p1.y = _nodes[i].y + ((+angle_next.x-angle_prev.x) / 2) * LINE_WIDTH;
var p2:Point = new Point;
// then the same procedure for the other side
p2.x = _nodes[i].x + ((+angle_next.y-angle_prev.y) / 2) * LINE_WIDTH;
p2.y = _nodes[i].y + ((-angle_next.x+angle_prev.x) / 2) * LINE_WIDTH;
// then add the two coordinates to the lists
coords1.push(p1);
coords2.push(p2);
}
// clear the graphics and get ready for drawing the next frame
graphics.clear();
graphics.lineStyle();
graphics.beginFill(Math.random()*0xffffff);
// move the draw head to the first coord in the list
graphics.moveTo(coords1[0].x, coords1[0].y);
// start by doing lines along one side
for (i = 0; i < coords1.length; i++) {
graphics.lineTo(coords1[i].x, coords1[i].y);
}
// and then draw the other side in reverse to get a fill that goes around the shape
for (i = coords2.length - 1; i >= 0; i--) {
graphics.lineTo(coords2[i].x, coords2[i].y);
}
graphics.endFill();
// finally draw the center line
graphics.lineStyle(3, 0);
graphics.moveTo(_nodes[0].x, _nodes[0].y);
for (i = 1; i < _nodes.length; i++) {
graphics.lineTo(_nodes[i].x, _nodes[i].y);
}
}
}
}