score:2

I am definitely not sure if I understand your question, but if you are trying to position circles along a curve, I would suggest...

  1. write the equation for the curve you want
  2. convert that curve to a parametric equation
  3. use the x equation for cx, use y equation for cy

The parametric equation will get you a single row. For each additional row you'll want to factor in an additional offset for all cy's in that row.

Here is a very rough example for you to build off of...

const p_circle = {
  x(t){ return 100*Math.cos((t+10)/10)+150 },
  y(t){ return 100*Math.sin((t+10)/10)-80 }
}

const p_parab = {
  x(t){ return -(10*t-5)+100 },
  y(t){ return -(t-5)*(t-5)+20 }
}



let t = Array.prototype.concat(
  Array.from(Array(10).keys()).map(d=>[d,1]), //row 1
  Array.from(Array(10).keys()).map(d=>[d,2]), //row 2
  Array.from(Array(10).keys()).map(d=>[d,3])  //row 3
)


const p_parab_2 = {
  x(t){ return (10*t-5)+100 }, // removing "-" so that first seat is on left, not right
  y(t){ return -(t-5)*(t-5)+20 }
}

// adding 11th seat to center around seat 5 (seat in the center)
let t2 = Array.prototype.concat(
  Array.from(Array(11).keys()).map(d=>[d,1]), //row 1
  Array.from(Array(11).keys()).map(d=>[d,2]), //row 2
  Array.from(Array(11).keys()).map(d=>[d,3])  //row 3
)

console.log(t)

d3.select("svg").selectAll(".circ")
  .data(t)
  .enter()
  .append("circle")
    .attr("class", "circ")
    .attr("r",5)
    .attr("fill","red")
    .attr("cx", (d) => p_circle.x(d[0]))
    .attr("cy", (d) => p_circle.y(d[0]) + 15*d[1])

d3.select("svg").selectAll(".parab2")
  .data(t2)
  .enter()
  .append("circle")
    .attr("class", "parab2")
    .attr("r",7)
    .attr("fill","blue")
    .attr("cx", (d) => p_parab.x(d[0]))
    .attr("cy", (d) => p_parab.y(d[0]) + 15*d[1])

d3.select("svg").selectAll(".parab")
  .data(t)
  .enter()
  .append("circle")
    .attr("class", "parab")
    .attr("r",5)
    .attr("fill","green")
    .attr("cx", (d) => p_parab.x(d[0]))
    .attr("cy", (d) => p_parab.y(d[0]) + 15*d[1])
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<svg height="250" width="250"></svg>

score:2

I like @steveladavich's answer but I'll propose an alternate. You can use d3's ability to curve fit to points and then place the circles on the resulting path:

var r = 10,
  points = [];
for (var i = 0; i < 10; i++) {
  points.push({
    x: (500 / 10) * i,
    y: Math.random() * 500
  });
}

var line = d3.line()
  .x(function(d) {
    return d.x;
  })
  .y(function(d) {
    return d.y;
  })
  .curve(d3.curveCardinal);

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 500);

var path = svg.append("g")
  .datum(points)
  .append("path")
  .attr("d", line)
  .style("fill", "none")
  .style("stroke", "none")
  .node();

var pathLength = path.getTotalLength();
svg.append("g")
  .selectAll("circle")
  .data(d3.range(0, pathLength, r))
  .enter()
  .append("circle")
  .attr("transform", function(d) {
    var p = path.getPointAtLength(d);
    return "translate(" + p.x + "," + p.y + ")";
  })
  .attr("r", r / 2)
  .style("fill", "steelblue");
<script src="http://d3js.org/d3.v4.js"></script>


Related Query

More Query from same tag