<svg> path创建一条曲线来连接两个点

时间:2017-07-21 14:36:57

标签: html svg path curve

我目前正在尝试使用js的SVG路径,并希望用曲线连接两个点。到目前为止,我的进展如下:

&#13;
&#13;
// 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);
&#13;
<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>
&#13;
&#13;
&#13;

CodePen版本here

它正在工作,但我找到的问题如下,当我在(endX,endY)右侧指向(startX,startY)时,我不想得到我想要的结果。 这就是我所拥有的:enter image description here 我想拥有什么: enter image description here

所以我似乎需要在路径中添加另一个curveTo。

此外,我发现此CodePen正在发挥作用。

1 个答案:

答案 0 :(得分:1)

不使用private void InitAdapter() { this._adapter = new global::System.Data.SqlClient.SqlDataAdapter(); global::System.Data.Common.DataTableMapping tableMapping = new global::System.Data.Common.DataTableMapping(); tableMapping.SourceTable = "Table"; tableMapping.DataSetTable = "Clients Intake"; tableMapping.ColumnMappings.Add("intakeDate", "intakeDate"); tableMapping.ColumnMappings.Add("firstName", "firstName"); tableMapping.ColumnMappings.Add("lastName", "lastName"); tableMapping.ColumnMappings.Add("disability", "disability"); tableMapping.ColumnMappings.Add("Employed", "Employed"); tableMapping.ColumnMappings.Add("returningClient", "returningClient"); tableMapping.ColumnMappings.Add("region", "region"); tableMapping.ColumnMappings.Add("lengthSinceEmployed", "lengthSinceEmployed"); tableMapping.ColumnMappings.Add("Resume", "Resume"); tableMapping.ColumnMappings.Add("Age", "Age"); tableMapping.ColumnMappings.Add("education", "education"); tableMapping.ColumnMappings.Add("mainIncomeSource", "mainIncomeSource"); tableMapping.ColumnMappings.Add("refferal", "refferal"); tableMapping.ColumnMappings.Add("cm", "cm"); tableMapping.ColumnMappings.Add("firstAppt", "firstAppt"); tableMapping.ColumnMappings.Add("Notes", "Notes"); tableMapping.ColumnMappings.Add("copingAndMovingForward", "copingAndMovingForward"); tableMapping.ColumnMappings.Add("SSMA_TimeStamp", "SSMA_TimeStamp"); this._adapter.TableMappings.Add(tableMapping); this._adapter.DeleteCommand = new global::System.Data.SqlClient.SqlCommand(); this._adapter.DeleteCommand.Connection = this.Connection; this._adapter.DeleteCommand.CommandText = @"DELETE FROM [dbo].[Clients Intake] WHERE (([intakeDate] = @Original_intakeDate) AND ([firstName] = @Original_firstName) AND ((@IsNull_lastName = 1 AND [lastName] IS NULL) OR ([disability] = @Original_disability)) AND (([Employed] = @Original_Employed)) AND ((@IsNull_returningClient = 1 AND [returningClient] IS NULL) OR ([returningClient] = @Original_returningClient)) AND ((@IsNull_region = 1 AND [region] IS NULL) OR ([region] = @Original_region)) AND ((@IsNull_lengthSinceEmployed = 1 AND [lengthSinceEmployed] IS NULL) OR ([lengthSinceEmployed] = @Original_lengthSinceEmployed)) AND ((@IsNull_Resume = 1 AND [Resume] IS NULL) OR ([Resume] = @Original_Resume)) AND ((@IsNull_Age= 1 AND [Age] IS NULL) OR ([Age] = @Original_Age)) AND ((@IsNull_education= 1 AND [education] IS NULL) OR ([education] = @Original_education)) AND ((@IsNull_mainIncomeSource= 1 AND [mainIncomeSource] IS NULL) OR ([mainIncomeSource] = @Original_mainIncomeSource)) AND ((@IsNull_refferal= 1 AND [refferal] IS NULL) OR ([refferal] = @Original_refferal)) AND ((@IsNull_cm= 1 AND [cm] IS NULL) OR ([cm] = @Original_cm)) AND ((@IsNull_firstAppt= 1 AND [firstAppt] IS NULL) OR ([firstAppt] = @Original_firstAppt)) AND ((@IsNull_Notes= 1 AND [Notes] IS NULL) OR ([Notes] = @Original_Notes)) AND ((@IsNull_copingAndMovingForward= 1 AND [copingAndMovingForward] IS NULL) OR ([copingAndMovingForward] = @Original_copingAndMovingForward)))"; this._adapter.DeleteCommand.CommandType = global::System.Data.CommandType.Text; this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@intakeDate", global::System.Data.SqlDbType.DateTime2, 0, global::System.Data.ParameterDirection.Input, 0, 0, "intakeDate", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@firstName", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "firstName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@lastName", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "lastName", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@disability", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "disability", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Employed", global::System.Data.SqlDbType.Bit, 0, global::System.Data.ParameterDirection.Input, 0, 0, "Employed", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@returningClient", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "returningClient", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@region", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "region", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@lengthSinceEmployed", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "lengthSinceEmployed", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Resume", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "Resume", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Age", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "Age", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@education", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "education", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@mainIncomeSource", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "mainIncomeSource", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@refferal", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "refferal", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@cm", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "cm", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@firstAppt", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "firstAppt", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@Notes", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "Notes", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); this._adapter.DeleteCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@copingAndMovingForward", global::System.Data.SqlDbType.NVarChar, 0, global::System.Data.ParameterDirection.Input, 0, 0, "copingAndMovingForward", global::System.Data.DataRowVersion.Current, false, null, "", "", "")); 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);