<svg> path 创建到 link 两点的曲线
<svg> path create a curvy line to link two points
我目前正在尝试使用 js 的 SVG 路径,并且想要 link 两个带有曲线的点。这是我目前的进度:
// draw a curvy line between point (startX,startY) and point (endX,endY)
function drawCurve(startX, startY, endX, endY) {
// exemple of a path: M318,345 L330,345 C450,345 380,124 504,124 L519,124
// M
var AX = startX;
var AY = startY;
// L
var BX = Math.abs(endX - startX) * 0.05 + startX;
var BY = startY;
// C
var CX = (endX - startX) * 0.66 + startX;
var CY = startY;
var DX = (endX - startX) * 0.33 + startX;
var DY = endY;
var EX = - Math.abs(endX - startX) * 0.05 + endX;
var EY = endY;
// L
var FX = endX;
var FY = endY;
// [DEBUGGING] add all the colored points for testing
document.getElementById('pointA').setAttribute("cx", AX);
document.getElementById('pointA').setAttribute("cy", AY);
document.getElementById('pointB').setAttribute("cx", BX);
document.getElementById('pointB').setAttribute("cy", BY);
document.getElementById('pointC').setAttribute("cx", CX);
document.getElementById('pointC').setAttribute("cy", CY);
document.getElementById('pointD').setAttribute("cx", DX);
document.getElementById('pointD').setAttribute("cy", DY);
document.getElementById('pointE').setAttribute("cx", EX);
document.getElementById('pointE').setAttribute("cy", EY);
document.getElementById('pointF').setAttribute("cx", FX);
document.getElementById('pointF').setAttribute("cy", FY);
// setting up the path string
var path = 'M' + AX + ',' + AY;
path += ' L' + BX + ',' + BY;
path += ' ' + 'C' + CX + ',' + CY;
path += ' ' + DX + ',' + DY;
path += ' ' + EX + ',' + EY;
path += ' L' + FX + ',' + FY;
// [DEBUGGING] display the path string
console.log('path is '+path);
// applying the new path to the element
document.getElementById('myPath').setAttribute("d", path);
}
drawCurve(200,400, 519,124);
<svg height="1000" width="1000">
<path id="myPath" d="" stroke="blue" stroke-width="5" fill="none" />
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointA" cx="318" cy="345" r="1" />
<circle id="pointB" cx="330" cy="345" r="1" />
</g>
<g stroke="red" stroke-width="3" fill="red">
<circle id="pointC" cx="450" cy="345" r="1" />
</g>
<g stroke="green" stroke-width="3" fill="green">
<circle id="pointD" cx="380" cy="124" r="1" />
</g>
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointE" cx="504" cy="124" r="1" />
<circle id="pointF" cx="519" cy="124" r="1" />
</g>
</svg>
CodePen 版本 here
它正在工作,但我发现的问题如下,当我在 (endX,endY) 的右侧点 (startX,startY) 时,我没有得到我想要的结果。
这是我拥有的:
我想要的是:
看来我需要在路径中添加另一个 curveTo。
我还发现这个 CodePen 有效。
不使用 startX
和 endX
之间的带符号差来计算贝塞尔曲线控制点的位置,而是使用绝对值。
此外,要获得第二个控制点,请从 endX
减去三分之一的距离,而不是将三分之二加到 startX
。
var CX = startX + Math.abs(endX - startX) * 0.33;
var DX = endX - Math.abs(endX - startX) * 0.33;
// draw a curvy line between point (startX,startY) and point (endX,endY)
function drawCurve(startX, startY, endX, endY) {
// exemple of a path: M318,345 L330,345 C450,345 380,124 504,124 L519,124
// M
var AX = startX;
console.log(AX);
var AY = startY;
// L
var BX = Math.abs(endX - startX) * 0.05 + startX;
var BY = startY;
// C
var CX = startX + Math.abs(endX - startX) * 0.33;
var CY = startY;
var DX = endX - Math.abs(endX - startX) * 0.33;
var DY = endY;
var EX = - Math.abs(endX - startX) * 0.05 + endX;
var EY = endY;
// L
var FX = endX;
var FY = endY;
// [DEBUGGING] add all the colored points for testing
document.getElementById('pointA').setAttribute("cx", AX);
document.getElementById('pointA').setAttribute("cy", AY);
document.getElementById('pointB').setAttribute("cx", BX);
document.getElementById('pointB').setAttribute("cy", BY);
document.getElementById('pointC').setAttribute("cx", CX);
document.getElementById('pointC').setAttribute("cy", CY);
document.getElementById('pointD').setAttribute("cx", DX);
document.getElementById('pointD').setAttribute("cy", DY);
document.getElementById('pointE').setAttribute("cx", EX);
document.getElementById('pointE').setAttribute("cy", EY);
document.getElementById('pointF').setAttribute("cx", FX);
document.getElementById('pointF').setAttribute("cy", FY);
// setting up the path string
var path = 'M' + AX + ',' + AY;
path += ' L' + BX + ',' + BY;
path += ' ' + 'C' + CX + ',' + CY;
path += ' ' + DX + ',' + DY;
path += ' ' + EX + ',' + EY;
path += ' L' + FX + ',' + FY;
// [DEBUGGING] display the path string
console.log(path);
// applying the new path to the element
document.getElementById('myPath').setAttribute("d", path);
}
//drawCurve(200,400, 519,124);
drawCurve(519,124, 200,400);
<svg height="1000" width="1000">
<path id="myPath" d="" stroke="blue" stroke-width="5" fill="none" />
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointA" cx="318" cy="345" r="1" />
<circle id="pointB" cx="330" cy="345" r="1" />
</g>
<g stroke="red" stroke-width="3" fill="red">
<circle id="pointC" cx="450" cy="345" r="1" />
</g>
<g stroke="green" stroke-width="3" fill="green">
<circle id="pointD" cx="380" cy="124" r="1" />
</g>
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointE" cx="504" cy="124" r="1" />
<circle id="pointF" cx="519" cy="124" r="1" />
</g>
</svg>
我目前正在尝试使用 js 的 SVG 路径,并且想要 link 两个带有曲线的点。这是我目前的进度:
// draw a curvy line between point (startX,startY) and point (endX,endY)
function drawCurve(startX, startY, endX, endY) {
// exemple of a path: M318,345 L330,345 C450,345 380,124 504,124 L519,124
// M
var AX = startX;
var AY = startY;
// L
var BX = Math.abs(endX - startX) * 0.05 + startX;
var BY = startY;
// C
var CX = (endX - startX) * 0.66 + startX;
var CY = startY;
var DX = (endX - startX) * 0.33 + startX;
var DY = endY;
var EX = - Math.abs(endX - startX) * 0.05 + endX;
var EY = endY;
// L
var FX = endX;
var FY = endY;
// [DEBUGGING] add all the colored points for testing
document.getElementById('pointA').setAttribute("cx", AX);
document.getElementById('pointA').setAttribute("cy", AY);
document.getElementById('pointB').setAttribute("cx", BX);
document.getElementById('pointB').setAttribute("cy", BY);
document.getElementById('pointC').setAttribute("cx", CX);
document.getElementById('pointC').setAttribute("cy", CY);
document.getElementById('pointD').setAttribute("cx", DX);
document.getElementById('pointD').setAttribute("cy", DY);
document.getElementById('pointE').setAttribute("cx", EX);
document.getElementById('pointE').setAttribute("cy", EY);
document.getElementById('pointF').setAttribute("cx", FX);
document.getElementById('pointF').setAttribute("cy", FY);
// setting up the path string
var path = 'M' + AX + ',' + AY;
path += ' L' + BX + ',' + BY;
path += ' ' + 'C' + CX + ',' + CY;
path += ' ' + DX + ',' + DY;
path += ' ' + EX + ',' + EY;
path += ' L' + FX + ',' + FY;
// [DEBUGGING] display the path string
console.log('path is '+path);
// applying the new path to the element
document.getElementById('myPath').setAttribute("d", path);
}
drawCurve(200,400, 519,124);
<svg height="1000" width="1000">
<path id="myPath" d="" stroke="blue" stroke-width="5" fill="none" />
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointA" cx="318" cy="345" r="1" />
<circle id="pointB" cx="330" cy="345" r="1" />
</g>
<g stroke="red" stroke-width="3" fill="red">
<circle id="pointC" cx="450" cy="345" r="1" />
</g>
<g stroke="green" stroke-width="3" fill="green">
<circle id="pointD" cx="380" cy="124" r="1" />
</g>
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointE" cx="504" cy="124" r="1" />
<circle id="pointF" cx="519" cy="124" r="1" />
</g>
</svg>
CodePen 版本 here
它正在工作,但我发现的问题如下,当我在 (endX,endY) 的右侧点 (startX,startY) 时,我没有得到我想要的结果。
这是我拥有的:
看来我需要在路径中添加另一个 curveTo。
我还发现这个 CodePen 有效。
不使用 startX
和 endX
之间的带符号差来计算贝塞尔曲线控制点的位置,而是使用绝对值。
此外,要获得第二个控制点,请从 endX
减去三分之一的距离,而不是将三分之二加到 startX
。
var CX = startX + Math.abs(endX - startX) * 0.33;
var DX = endX - Math.abs(endX - startX) * 0.33;
// draw a curvy line between point (startX,startY) and point (endX,endY)
function drawCurve(startX, startY, endX, endY) {
// exemple of a path: M318,345 L330,345 C450,345 380,124 504,124 L519,124
// M
var AX = startX;
console.log(AX);
var AY = startY;
// L
var BX = Math.abs(endX - startX) * 0.05 + startX;
var BY = startY;
// C
var CX = startX + Math.abs(endX - startX) * 0.33;
var CY = startY;
var DX = endX - Math.abs(endX - startX) * 0.33;
var DY = endY;
var EX = - Math.abs(endX - startX) * 0.05 + endX;
var EY = endY;
// L
var FX = endX;
var FY = endY;
// [DEBUGGING] add all the colored points for testing
document.getElementById('pointA').setAttribute("cx", AX);
document.getElementById('pointA').setAttribute("cy", AY);
document.getElementById('pointB').setAttribute("cx", BX);
document.getElementById('pointB').setAttribute("cy", BY);
document.getElementById('pointC').setAttribute("cx", CX);
document.getElementById('pointC').setAttribute("cy", CY);
document.getElementById('pointD').setAttribute("cx", DX);
document.getElementById('pointD').setAttribute("cy", DY);
document.getElementById('pointE').setAttribute("cx", EX);
document.getElementById('pointE').setAttribute("cy", EY);
document.getElementById('pointF').setAttribute("cx", FX);
document.getElementById('pointF').setAttribute("cy", FY);
// setting up the path string
var path = 'M' + AX + ',' + AY;
path += ' L' + BX + ',' + BY;
path += ' ' + 'C' + CX + ',' + CY;
path += ' ' + DX + ',' + DY;
path += ' ' + EX + ',' + EY;
path += ' L' + FX + ',' + FY;
// [DEBUGGING] display the path string
console.log(path);
// applying the new path to the element
document.getElementById('myPath').setAttribute("d", path);
}
//drawCurve(200,400, 519,124);
drawCurve(519,124, 200,400);
<svg height="1000" width="1000">
<path id="myPath" d="" stroke="blue" stroke-width="5" fill="none" />
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointA" cx="318" cy="345" r="1" />
<circle id="pointB" cx="330" cy="345" r="1" />
</g>
<g stroke="red" stroke-width="3" fill="red">
<circle id="pointC" cx="450" cy="345" r="1" />
</g>
<g stroke="green" stroke-width="3" fill="green">
<circle id="pointD" cx="380" cy="124" r="1" />
</g>
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointE" cx="504" cy="124" r="1" />
<circle id="pointF" cx="519" cy="124" r="1" />
</g>
</svg>