Путь ‹svg› создает изогнутую линию, чтобы соединить две точки

В настоящее время я пробую пути SVG с помощью js и хотел бы связать две точки изогнутой линией. Вот мой прогресс:

// 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 здесь

Это работает, но проблема, которую я обнаружил, заключается в следующем: когда я указываю (startX, startY) справа от (endX, endY), я не получаю желаемого результата. Вот что у меня есть: введите описание изображения здесь И что я хотел бы иметь: введите здесь описание изображения

Так что, похоже, мне нужно добавить еще одну кривую в путь.

Также я нашел этот CodePen, который работает.


person Ivan    schedule 21.07.2017    source источник


Ответы (1)


Вместо использования знаковой разницы между 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>

person Paul LeBeau    schedule 21.07.2017
comment
О, хороший друг, я пробовал пресс, но у меня не получилось правильно. Я попробую в редакторе и приму ваш ответ. Большое спасибо! - person Ivan; 21.07.2017