svg中给出两点的坐标得到连接两点的曲线路径.
中心思想:求出两点连线的中垂线公式,给定AB某一点的X或Y坐标,求出中垂线上的另一个坐标
在svg中,我们画曲线的时候需要知道曲线的生成公式-----贝塞尔曲线.
根据图像,我们可以轻易的知道贝塞尔曲线的原理,他是由 起点-控制点-控制点-...-终点 之间的连线,从之中再取相领两根线的某一个点连线,取其中点绘制出来的曲线.
当然我们现在只是想随意的画出一条看的过去的曲线,所以我们的目标是得到一个控制点
从上图我们可以看出来控制点2(绿色)画出来的线是比较好看的.而这种线不偏向某一边的线的控制点都是在这两个点连线的中垂线上的
所以我们的重心落到了求出两点的中垂线上.
下面的问题就比较简单了
function svgPathCurv(a,b,curv) {
/*
* 弯曲函数.
* a:a点的坐标{x:10,y:10}
* b:b点的坐标{x:10,y:20}
* curv:弯曲程度 取值 -5 到 5
*/
curv = curv ? curv : 0;
var x1, x2, y1, y2, s, k2, controX, controY, q, l, path = '';
var s = 'M' + a.x + ',' + a.y + ' ';
/*
* 控制点必须在line的中垂线上
* **求出k2的中垂线(中垂线公式)**
*/
k2 = -(x2 - x1) / (y2 - y1);
/*
* 弯曲程度是根据中垂线斜率决定固定控制点的X坐标或者Y坐标,通过中垂线公式求出另一个坐标
* 默认A/B中点的坐标+curv*30,可以通过改基数30改变传入的参数范围
*/
if(k2 < 2 && k2 > -2) {
controX = (x2 + x1) / 2 + curv * 30;
controX = controX < 0 ? -controX : controX;
controY = k2 * (controX - (x1 + x2) / 2) + (y1 + y2) / 2;
controY = controY < 0 ? -controY : controY;
} else {
controY = (y2 + y1) / 2 + curv * 30;
controY = controY < 0 ? -controY : controY;
controX = (controY - (y1 + y2) / 2) / k2 + (x1 + x2) / 2;
controX = controX < 0 ? -controX : controX;
}
//定义控制点的位置
q = 'Q' + controX + ',' + controY + ' ';
//l=lineto
l = x2 + ',' + y2 + ' ';
//结果例: M10,10Q35,15,10,20
path = s + q + l;
return path;
}