geliokant
geliokant

Reputation: 25

SVG create elements on path phenomenon

I have a problem with creating "points" on path, if I'm creating more than 2 "points" they begin to "merge" and on a simple straight path everything is OK.

<path id="path" stroke="black" d="M436.3,583.7C561.4,788.6,726.6,968.7,921,1109.7c99.8,72.4,208.5,134.7,326.5,172.1c127.2,40.3,261.7,48.9,394.4,48
c127.8-0.9,256.5-9.7,381.3-38.6c122.6-28.4,234.3-79.4,340.5-146.2c100.8-63.5,196.8-135.2,303.6-188.6
c107.3-53.6,225.3-84.3,345.6-84.6c214.7-0.5,425.8,102.5,541.2,286.8c13.8,22.1,26,45.1,36.6,68.9c0.8,1.7-1.8,3.3-2.6,1.5
c-92.9-208.4-306.1-339.5-530.6-353c-126-7.6-252.6,18.9-366.7,72.3c-109,51-206.3,122.8-307.2,187.5
c-102.1,65.5-208.5,119-326.3,150c-120.3,31.7-245,43.3-369,46.2c-128,3-257.8-0.9-382.8-31.1c-118.9-28.8-229.5-83.4-331.2-150.7
c-194.1-128.7-362.2-298-492.7-490.7c-16.5-24.4-32.4-49.2-47.7-74.3C432.7,583.6,435.3,582.1,436.3,583.7L436.3,583.7z"/>

<script type="text/javascript"><![CDATA[

var el        = document.getElementById("path");
var len       = parseInt(el.getTotalLength());
var userValue = parseInt(prompt('Enter Integer from 2 to 100:'));
var modulo    = parseInt(len / userValue);

for (i = 0; i < len; i++) {

if (i % modulo ) { continue; }

var dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
dot.setAttributeNS(null, "cx", el.getPointAtLength(i).x );
dot.setAttributeNS(null, "cy", el.getPointAtLength(i).y );
dot.setAttributeNS(null, "r", '25');
dot.setAttributeNS(null, "fill", "red");
document.getElementById("container").appendChild(dot);
}]]></script>

Screenshot 1

Screenshot 2

Upvotes: 1

Views: 48

Answers (1)

Bobby Orndorff
Bobby Orndorff

Reputation: 3335

In the HTML: The path follows some curves out and then follows the same curves back to the starting point which creates a closed path. The first and last circle will be at the same point. The second and next to last circle will be at the same place. And so on. Did you intend to create an open path that does not loop back on itself? For example...

<path id="path" fill="none" stroke="black" d="M436.3,583.7C561.4,788.6,726.6,968.7,921,1109.7c99.8,72.4,208.5,134.7,326.5,172.1c127.2,40.3,261.7,48.9,394.4,48
    c127.8-0.9,256.5-9.7,381.3-38.6c122.6-28.4,234.3-79.4,340.5-146.2c100.8-63.5,196.8-135.2,303.6-188.6
    c107.3-53.6,225.3-84.3,345.6-84.6c214.7-0.5,425.8,102.5,541.2,286.8c13.8,22.1,26,45.1,36.6,68.9c0.8,1.7-1.8,3.3-2.6,1.5"/>

In the JavaScript: The total distance of the path (i.e. getTotalLength()) is a float. The distance between circles (i.e. getTotaleLength()/(uservalue-1)) is a float. The code was converting both of these values to integers which loses the decimal part of the values which messes up the later calculations. One solution is to step i from 0 to userValue - 1 and then calculate distance along path of the ith circle. For example...

var el = document.getElementById("path");
var totalLength = el.getTotalLength();
var userValue = parseInt(prompt('Enter Integer from 2 to 100:'), 10);
for (i = 0; i < userValue; i++) {
    var distance = (i / (userValue - 1)) * totalLength;
    var dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    dot.setAttributeNS(null, "cx", el.getPointAtLength(distance).x );
    dot.setAttributeNS(null, "cy", el.getPointAtLength(distance).y );
    dot.setAttributeNS(null, "r", '25');
    dot.setAttributeNS(null, "fill", "red");
    document.getElementById("container").appendChild(dot);
}

Note: When calling parseInt() function, it is a good practice to specify radix.

Upvotes: 1

Related Questions