Пожалуйста, попробуйте следующий код. Это не идеально, но, вероятно, может дать вам некоторое представление.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
public class CurvedLineTest extends Sprite
{
private static const DRAW_STEP:Number = 2;
private var curveWidth:Number;
private var curvePeriod:Number;
private var smoothing:Number;
private var prevPos:Point = new Point();
private var curveLength:Number;
private var smoothedN:Point = new Point();
public function CurvedLineTest(curveWidth:Number = 10, curvePeriod:Number = 15, smoothFactor:Number = 80)
{
this.curveWidth = curveWidth;
this.curvePeriod = curvePeriod;
this.smoothing = Math.min(Math.max(smoothFactor, 0), 100) / 100;
if( stage )
{
onAddedToStage();
}
else addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
// test: simulating fast mouse movements
moveToPoint(10, 10);
drawToPoint(15, 15);
drawToPoint(35, 35);
drawToPoint(60, 90);
drawToPoint(150, 190);
drawToPoint(350, 300);
}
private function onAddedToStage(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
}
private function onRemovedFromStage(e:Event):void
{
removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onMouseDown(e:MouseEvent):void
{
moveToPoint(mouseX, mouseY);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function onMouseMove(e:MouseEvent):void
{
drawToPoint(mouseX, mouseY);
e.updateAfterEvent();
}
private function moveToPoint(x:Number, y:Number):void
{
prevPos.x = x;
prevPos.y = y;
curveLength = 0;
graphics.moveTo(x, y);
}
private function drawToPoint(x:Number, y:Number):void
{
// displacement vector
var d:Point = new Point(x - prevPos.x, y - prevPos.y);
// length of displacement vector
var dl:Number = Math.sqrt(d.x * d.x + d.y * d.y);
// normalized displacement vector
var nd:Point = new Point(d.x / dl, d.y / dl);
// normal to the displacement vector
var cn:Point = normal(nd);
var currentDl:Number = DRAW_STEP;
while( currentDl <= dl )
{
// incrementing base curve length by the length of the step displacement
curveLength += DRAW_STEP;
// base curve coords of the current step
var stepX:Number = prevPos.x + nd.x * DRAW_STEP;
var stepY:Number = prevPos.y + nd.y * DRAW_STEP;
// smoothing the normal to prevent ragged lines
smoothedN.x = smoothing * smoothedN.x + (1 - smoothing) * cn.x;
smoothedN.y = smoothing * smoothedN.y + (1 - smoothing) * cn.y;
// wave form
var wave:Number = curveWidth * Math.sin(Math.PI * curveLength / curvePeriod);
// adding normal component to the current point of base curve
var wavedX:Number = stepX + wave * smoothedN.x;
var wavedY:Number = stepY + wave * smoothedN.y;
// drawing waved curve
graphics.lineStyle(1.5, 0);
graphics.lineTo(wavedX, wavedY);
// drawing base curve
graphics.lineStyle(0, 0xBB2233, 0.5);
graphics.moveTo(prevPos.x, prevPos.y);
graphics.lineTo(stepX, stepY);
// drawing normal
graphics.lineStyle(0, 0x3322BB, 0.2);
graphics.moveTo(prevPos.x, prevPos.y);
graphics.lineTo(stepX + wave * smoothedN.x, stepY + wave * smoothedN.y);
graphics.moveTo(wavedX, wavedY);
// remembering current base curve point
prevPos.x = stepX;
prevPos.y = stepY;
currentDl += DRAW_STEP;
}
}
/**
* Calculates normal to the given vector (in clockwise direction).
*/
private function normal(vec:Point):Point
{
var d:Number = Math.sqrt(vec.x * vec.x + vec.y * vec.y);
return new Point(-vec.y / d, vec.x / d);
}
private function onMouseUp(e:MouseEvent):void
{
graphics.clear();
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
}
}