Reputation: 113
I have now been asked by a client to draw a wavy line with the cursor/mouse such as the following:
(source: endeavoursportsgroup.com)
I have the following code below which draws a line with the cursor/mouse, but I am stuck on how to make the line "wavy". This is actually modified code from drawing a dashed line I was working on earlier, so there may be some left over code from that which I will remove later.
Can someone help me achieve the Wavy Line that I have been asked to create with my code below or suggest another way to achieve this?
Thanks in advance!
package
{
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.net.FileReference;
import flash.utils.ByteArray;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.graphics.codec.PNGEncoder;
public class DrawingArea extends UIComponent
{
private var isDrawing:Boolean = false;
private var x1:int;
private var y1:int;
private var x2:int;
private var y2:int;
private var LastX:int = 0;
private var LastY:int = 0;
public var drawColor:uint = 0x0000FF;
public function DrawingArea()
{
super();
var p1:Point = new Point();
var p2:Point = new Point();
p1.x = 0;
p1.y = 0;
p2.x = 200;
p2.y = 200;
addEventListener(FlexEvent.CREATION_COMPLETE, function(event:FlexEvent):void {
graphics.clear();
graphics.beginFill(0xffffff, 0.00001);
graphics.drawRect(0, 0, width, height);
graphics.endFill();
});
addEventListener( MouseEvent.MOUSE_DOWN, mouseDown );
addEventListener( MouseEvent.MOUSE_MOVE, mouseMove );
addEventListener( MouseEvent.MOUSE_UP, mouseUp);
}
private function mouseDown(event:MouseEvent):void {
x1 = mouseX;
y1 = mouseY;
isDrawing = true;
}
private function mouseMove(event:MouseEvent):void {
if (!event.buttonDown)
{
isDrawing = false;
}
x2 = mouseX;
y2 = mouseY;
if (isDrawing )
{
var p1:Point = new Point();
var p2:Point = new Point();
p1.x = x1;
p1.y = y1;
p2.x = x2;
p2.y = y2;
graphics.lineStyle(2,0x00FF00,2);
graphics.lineStyle(1, drawColor);
graphics.moveTo(x1, y1);
graphics.lineTo(x2, y2);
x1 = x2;
y1 = y2;
LastX = x2;
LastY = y2;
}
}
private function mouseUp(event:MouseEvent):void {
isDrawing = false;
}
}
}
Upvotes: 2
Views: 1170
Reputation: 1
Another possibility would be spark.Path
and a pattern using QuadraticBezier
.
I believe the documentation gives pretty detailed explanation and examples.
Upvotes: 0
Reputation: 3899
Please try the following code. It is not ideal, but it can probably give you some idea.
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);
}
}
}
Upvotes: 1
Reputation: 333
It is a Sin(or Cos) Curve. Changing your MouseMove to this should fix it. I am assuming the Points and 'Last' variables were old. This should move the Y coordinate up or down depending on where you are in the curve using your x coordinate as the angle in radians.
private function mouseMove(event:MouseEvent):void {
if (!event.buttonDown)
{
isDrawing = false;
}
x2 = mouseX;
y2 = mouseY;
if (isDrawing )
{
//var p1:Point = new Point();
// var p2:Point = new Point();
// p1.x = x1;
// p1.y = y1;
// p2.x = x2;
// p2.y = y2;
y2 = Math.Sin(x2)+y2*(HeightOfThe Curve)
graphics.lineStyle(2,0x00FF00,2);
graphics.lineStyle(1, drawColor);
graphics.moveTo(x1, y1);
graphics.lineTo(x2, y2);
x1 = x2;
y1 = y2;
//LastX = x2;
// LastY = y2;
}
}
Negatives should automatically be accounted for.
Again I have NO idea how to make it work on a curved line. It will work fine but it would look funky until you get back to a horizontal(or at least mostly horizontal) movement.
I can't test it on my own at the moment but I think that is all you need to do if you already know how to draw a straight Line.
Upvotes: 0