在两点之间绘制平滑曲线 arc()
Posted
技术标签:
【中文标题】在两点之间绘制平滑曲线 arc()【英文标题】:Drawing a smooth curved arc() between two points 【发布时间】:2013-12-19 15:49:21 【问题描述】:我正在尝试在画布中的两点之间绘制一条平滑的弧线,我已将这些点设置为 sutch note,这些点是动态的并且可以更改。
var p1 =
x=100, y=100
var p2 =
x=255, y=255
曲线看起来像这样
这是我开始的代码,我无法理解这个函数的数学/逻辑:
function curveA2B(a,b)
var mindpoint =
x: (a.x+b.x)/2,
y: (a.y+b.y)/2,
d: Math.sqrt(Math.pow(b.x-a.x,2) + Math.pow(b.y-a.y,2))
;
context.beginPath();
context.arc(
a.x,
a.y,
mindpoint.d/2,
1.5*Math.PI,
0,
false
);
context.arc(
b.x,
b.y,
mindpoint.d/2,
1*Math.PI,
0.5*Math.PI,
true
);
context.context.stroke();
动态例子在这里:http://jsfiddle.net/CezarisLT/JDdjp/6/
【问题讨论】:
how to draw smooth curve through N points using javascript html5 canvas?的可能重复 提示:思考三角形。 提示:想想样条曲线! @DevlshOne:您引用的上一个 SO 答案有一个很好的例子,用样条连接点。样条曲线只是一组单独的二次曲线,它们被设计成看起来像一条穿过给定点集的曲线。 【参考方案1】:您可以使用两个点的中点作为 x 和 y 轴的两个半径设置。
以下示例已简化,但它显示了一种在框内创建平滑曲线的方法,如您的示例所示。
框将始终缩放,使曲线穿过两点之间的中点(例如更改终点)。
DEMO
/// set up some values
var ctx = demo.getContext('2d'),
p1 = x:100, y:100, /// point 1
p2 = x:355, y:255, /// point 2
mx = (p2.x - p1.x) * 0.5, /// mid-point between point 1 and 2
my = (p2.y - p1.y) * 0.5,
c1 = x: p1.x, y: p1.y + my, /// create center point objects
c2 = x: p2.x, y: p2.y - my,
steps = 0.05; /// curve resolution
/// mark the points and the boxes which represent the center of those
ctx.fillStyle = '#ff6e6e';
ctx.fillRect(p1.x, p1.y, mx, my);
ctx.fillStyle = '#6e93ff';
ctx.fillRect(p1.x + mx, p1.y + my, mx, my);
然后我们为每个“盒子”渲染四分之一椭圆:
/// render the smooth curves using 1/4 ellipses
ctx.beginPath();
for(var isFirst = true, /// first point is moveTo, rest lineTo
angle = 1.5 * Math.PI, /// start angle in radians
goal = 2 * Math.PI, /// goal angle
x, y; angle < goal; angle += steps)
/// calculate x and y using cos/sin
x = c1.x + mx * Math.cos(angle);
y = c1.y + my * Math.sin(angle);
/// move or draw line
(isFirst) ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
isFirst = false;
/// second box
for(var isFirst = true,
angle = Math.PI,
goal = 0.5 * Math.PI,
x, y;angle > goal; angle -= steps)
x = c2.x + mx * Math.cos(angle);
y = c2.y + my * Math.sin(angle);
(isFirst) ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
isFirst = false;
ctx.stroke();
我会留给你把它放到可重用的函数中。希望这会有所帮助!
如果还是不行,我建议你看看我的cardinal spline implementation。
【讨论】:
【参考方案2】:我创建了一个可以很容易地根据许多需求修改的函数,称为 plot_curve,它可以让您了解问题的分解。
快速演示:http://jsfiddle.net/LVFat/
function plot_curve(x,y,xx,yy, target,color)
var startX=x;
var startY=y;
var endX=xx;
var endY=yy;
var diff_x = xx - x;
var diff_y = yy - y;
var bezierX=x; // x1
var bezierY=yy; // y2
console.log("bx:"+bezierX);
console.log("by:"+bezierY);
var cx,cy, t;
for(t=0.0; t<=1; t+=0.01)
cx = Math.round( (1-t)*(1-t)*startX + 2*(1-t) * t * bezierX + t*t*endX);
cy = Math.round( (1-t)*(1-t)*startY + 2*(1-t) * t * bezierY + t*t*endY);
// change this part to whatever you are trying to manipulate to the curve
plot_pixel( Math.round(cx), Math.round(cy), target, color);
示例...(与我制作的 divCanvas 函数一起使用...查看 jsfiddle 链接...)
plot_curve(25,25,5,5, ".divCanvas","blue");
如果你只想要两点之间曲线的坐标,试试这个:
function plot_curve(x,y,xx,yy)
// returns an array of x,y coordinates to graph a perfect curve between 2 points.
var startX=x;
var startY=y;
var endX=xx;
var endY=yy;
var diff_x = xx - x;
var diff_y = yy - y;
var xy = [];
var xy_count = -1;
var bezierX=x; // x1
var bezierY=yy; // y2
var t;
for(t=0.0; t<=1; t+=0.01)
xy_count++;
xy[xy_count] = ;
xy[xy_count].x = Math.round( (1-t)*(1-t)*startX + 2*(1-t) * t * bezierX + t*t*endX);
xy[xy_count].y = Math.round( (1-t)*(1-t)*startY + 2*(1-t) * t * bezierY + t*t*endY);
return xy; // returns array of coordinates
【讨论】:
你能帮我减小曲线的大小吗?我只想要一条轻微的曲线,而不是演示中指定的曲线。 prnt.sc/pxh6w6以上是关于在两点之间绘制平滑曲线 arc()的主要内容,如果未能解决你的问题,请参考以下文章
Canvas HTML - lineTo 和 Bezier 曲线之间的平滑度
如何使用javascript HTML5画布通过N个点绘制平滑曲线?