score:1
Instead of using width
, you should use getTotalLength()
for the size of the line:
pathLength = this.getTotalLength();
Here is the demo with that change only:
function curve(val) {
var w = d3.select("#new_row_1").attr("width");
var
numLines = 1,
lineSpacing = 18,
parabDepth = -30;
var row_spacing = 18;
if (val == 0) {
parabDepth = -18;
} else if (val == 1) {
parabDepth = 0;
} else if (val == 15) {
parabDepth = 150;
row_spacing = 20;
} else {
parabDepth = val * 10;
}
width = w;
var curveData = [];
curveData.push([0, 0]);
curveData.push([width / 3 * 1, lineSpacing + parabDepth]);
curveData.push([width / 3 * 2, lineSpacing + parabDepth]);
curveData.push([width / 3 * 3 - 8, - 8]);
var line = d3.line()
.x(function(d) {
return d[0];
})
.y(function(d) {
return d[1];
})
.curve(d3.curveCardinal);
var svg = d3.select("#new_row_1").attr("height", (numLines * lineSpacing) + lineSpacing + parabDepth + row_spacing).attr("width", width);
var g = svg.selectAll(".line")
.data(d3.range(numLines))
.enter()
.append("g")
.attr("class", "line")
.attr("transform", function(d) {
return "translate(7," + (d * lineSpacing + 7) + ")";
});
var path = g.append("path")
.attr("d", line(curveData))
.style("fill", "none")
.style("stroke", "pink")
.style("stroke-width", "4")
.each(function() {
var g = d3.select(this.parentNode),
self = d3.select(this),
pathLength = this.getTotalLength();
g.selectAll("circle")
.data(d3.range(1, pathLength, row_spacing))
.enter()
.append("circle")
.attr("transform", (d, i) => {
var p = this.getPointAtLength(d);
return "translate(" + p.x + "," + p.y + ")";
})
.attr("r", 7)
.style("fill", "darkslategray")
.attr("stroke", "black")
.attr("stroke-width", "1");
});
}
setTimeout(function() {
curve(5)
}, 500)
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="252" height="18" id="new_row_1" class="new_row" style="top: 150px; left: 302px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><g><circle cx="8" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="3" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">1</text></g><g><circle cx="26" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="21" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">2</text></g><g><circle cx="44" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="39" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">3</text></g><g><circle cx="62" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="57" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">4</text></g><g><circle cx="80" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="75" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">5</text></g><g><circle cx="98" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="93" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">6</text></g><g><circle cx="116" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="111" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">7</text></g><g><circle cx="134" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="129" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">8</text></g><g><circle cx="152" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="147" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">9</text></g><g><circle cx="170" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="165" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">10</text></g><g><circle cx="188" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="183" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">11</text></g><g><circle cx="206" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="201" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">12</text></g><g><circle cx="224" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="219" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">13</text></g><g><circle cx="242" cy="8" r="7" style="fill: white; stroke: black; stroke-width: 1;"></circle><text dx="237" dy="11" class="label" style="font-size: 10px; font-weight: 500; display: none;">14</text><g class="label" style="display: none;"><rect x="126" y="1" width="14" height="14" style="fill: black;"></rect><text dx="130" dy="11" style="font-size: 9px; font-weight: 400; fill: white;">A</text></g></g></svg>
Alternatively, if you want to use width
, you shouldn't use getPointAtLength()
, as LeBeau explains in his answer, because in Euclidean geometry a straight line is shorter than any other geometric shape going from point A to point B.
Besides that, you have two problems: 1. there are a lot of magic numbers everywhere, and 2. you could design a better math to get the arc. I believe you should get rid of this code and write an entirely new, different approach.
score:2
You are using getPointAtLength()
to find the X,Y coordinates of a point at a distance along the curve. Obvoiously that's wrong. You want to find the Y coord for a given X.
There is no built-in SVG function for that. You are going to have to calculate that yourself. For that you would need the polynomial form of the bezier equation, which is not trivial.
Since you are only making a parabola, you would be better to avoid using bezier curves at all, and just calculate your curve using the normal simple quadratic equation (ax^2 + bx + c).
Aside: if you do decide to stick with bezier curves, then you should really use a quadratic bezier, instead of a cbic one. Quadratic beziers have the property that they always form a segmnt of a parabola.
Source: stackoverflow.com
Related Query
- How to plot svg circles on curved line in d3 js?
- How to position svg circles on a line and curve it?
- In d3, how to get the interpolated line data from a SVG line?
- How to show a tooltip with value when mouseover a svg line graph using d3.js?
- How can I set the each line color or width in SVG path
- how do you draw linear line in scatter plot with d3.js
- How to fill an image inside my svg circles in d3.js
- How to add filled sections to SVG circles using d3.js
- How to plot animated line chart using d3 while the data table is required to be updated every 1 second?
- How to select and deselect a svg line and change its color on selection and deselection using d3.js and javascript , jquery?
- dc.js to plot line chart, How to break line if data is not present
- How to add circles onto line chart path d3.js
- I am trying to use multiple 2 arrays for binding data for svg circles but cannot figure out how
- How to plot different line patterns for different lines in DC.js series chart?
- How to reuse the same pattern on multiple svg circles in d3.js
- How to plot a straight line in d3.js by user interaction
- How to create one line plot per color series in Observable Plot?
- How to update all data representing an SVG line using d3?
- How to redraw the svg filled with circles in D3?
- How to draw a line dynamically between two circles
- d3 how to render 15 circles every line
- How do I do a line break with SVG text element ?
- How do you plot a line using scaleOrdinal in D3.js?
- How to normalize data in d3 and plot the lines in the axis independent of other line ranges
- How to properly add padding to the plot area in a D3 line chart?
- How to dynamically create append svg line using d3js?
- How to keep circles inside the svg when updating data in bubble chart
- How do i plot multiple lines in the same line graph using the D3 framework?
- How to display a straight line on svg in D3.js?
- How to hide a certain path line in svg using just css?
More Query from same tag
- d3 embeded image displayed twice
- D3.js - Setting a minimum and maximum range for a drag event
- d3.js, multiple script tags blocking eachother
- How to get the selection which is being dragged in d3.js?
- How to import a json file using angular and typescript
- Prevent the y-axis in a d3 line graph from going below 0 on drag
- How can I figure out what button was clicked on last?
- d3.js - Plotting points on zoomable, clickable map
- d3: Optionally add child elements based on node content in force layout
- Property 'forEach' does not exist on type '{}'
- d3-force - Nodes are dragged away from links, ticks not run
- Synchronous Angular 8 HTTP request from a service
- dc.js bubble chart fails to display points
- D3js and specific datapoints shown as small circles
- What is the use of the plus sign here?
- Correctly Overlay DC.JS (D3) canvas elements
- How to draw multiple item in single data iteration in D3?
- Clip path at center produce unexpected behavior with draggable images
- D3 - Uncaught TypeError: Cannot read property 'length' of undefined
- If else statement that disables a button
- Managing large hierarchical data (collapsible tree) with auto-zooming to the expanded node
- select("svg") - difference between two alternatives
- Publishing interactive scientific results in Python
- D3.js with update button adds new data to old instead of replacing old data
- D3 - Update chart based on data keys
- Sankey-diagram PowerBI custom visual with color nodes and ordering
- d3js step-after line graph - highlight line between two points on mouseover
- Uncaught TypeError: svg.append(...).attr(...).selectAll(...).data(...).enter is not a function
- D3 Getting values from keys using array of objects
- d3.js: How to access data in outer scope when using function(d) {...}