以鼠标为控制点,在两点间画一个曲线,相对来说比较容易,只要curveTo 就可以了,那么如果要让这个曲线过鼠标该怎么办呢?
我想了一个办法,就是将曲线的起止点之间的距离缩小(比如缩小两倍),并“移动”到鼠标的两侧,让鼠标和这两个新位置点位于同一条直线上,然后以鼠标两侧的点为控制点,以曲线的起止点和鼠标位置为新的曲线起止点,依次连接起来,就可以得到过鼠标的贝塞尔曲线了。代码如下:
stage.frameRate = 30;
var line:Sprite = new Sprite();
addChild(line);
var startDot:Point = new Point(450,100);
var endDot:Point = new Point(150,300);
var curveRate = 2; // 这个值越大,曲线在鼠标附近的弯曲度就越大,感觉上取2或3比较的合适。
var distPt:Point = new Point( (startDot.x - endDot.x)/curveRate,(startDot.y - endDot.y)/curveRate);
this.addEventListener(Event.ENTER_FRAME, drawLine);
function drawLine(e:Event):void {
var pen:Graphics = line.graphics;
//曲线
pen.clear();
pen.lineStyle(1);
var controlDot1:Point = new Point(mouseX + distPt.x/2,mouseY + distPt.y/2);
pen.moveTo(startDot.x,startDot.y);
pen.curveTo(controlDot1.x,controlDot1.y,mouseX,mouseY);
var controlDot2:Point = new Point(mouseX - distPt.x/2,mouseY - distPt.y/2);
pen.curveTo(controlDot2.x,controlDot2.y,endDot.x,endDot.y);
//控制线
pen.lineStyle(1,0xff0000,0.3);
pen.moveTo(startDot.x,startDot.y);
pen.lineTo(controlDot1.x,controlDot1.y);
pen.lineTo(controlDot2.x,controlDot2.y);
pen.lineTo(endDot.x,endDot.y);
}
//2008-11-15 补充下段文字:
古人说的好“吾尝终日而思,不如须臾之所学”,翻了一下 fl 基理大师译的 foundation ,里面提供了一个简单的算法,直接用一个控制点来实现曲线的绘制。
公式如下:
var ctlPtX = mouseX * 2 - (startDot.x + endDot.x) / 2;
var ctlPtY = mouseY * 2 - (startDot.y + endDot.y) / 2;
想了一下,相当于将我的两个控制点的做法,与曲线的起止点连起来延长得到交点,就是唯一的控制点,参数取2。
代码修改一下,复制放到场景中可以看到最终效果。
stage.frameRate = 30;
var line:Sprite = new Sprite();
addChild(line);
var startDot:Point = new Point(450,100);
var endDot:Point = new Point(150,300);
this.addEventListener(Event.ENTER_FRAME, drawLine);
function drawLine(e:Event):void {
var pen:Graphics = line.graphics;
pen.clear();
pen.lineStyle(1);
//曲线
var ctlPtX = mouseX * 2 - (startDot.x + endDot.x) / 2;
var ctlPtY = mouseY * 2 - (startDot.y + endDot.y) / 2;
pen.moveTo( startDot.x,startDot.y );
pen.curveTo( ctlPtX,ctlPtY,endDot.x,endDot.y);
//控制线
pen.lineStyle(1,0xff0000,0.3);
pen.lineTo(ctlPtX,ctlPtY);
pen.lineTo( startDot.x,startDot.y );
}