Reputation: 1389
I am making a software like seats.io and I'm trying to curve the line of the circles. I start by creating a square with svg circles, using d3.js.
The y coordinates
I've started by finding the middle circle and setting it's cy to 0 and the subsequent ones in sequence (incrementing 12 each row. Then I realized that if it was an even number it couldn't find the middle point.
I've decided to use bhaskara formula to find the curve coordinates but I'm stuck on how to position it inside the loop:
$("#curve").on("change",function(){
var a = $(this).val();
var q = quant_col2;
console.log(q);
console.log(quant_line2);
var half = Math.round(quant_col2/2) - 1;
console.log("media: " + half);
var value = 0;
var circles = svg.selectAll("circle").attr("cy", function(d, i){
var cy = $(this).attr("cy");
var resultado = baskara(quant_col2,quant_line2,0);
var xv = -Math.abs(quant_line2)/(2 * quant_col2);
var xy = -Math.abs(delta(quant_col2,quant_line2,0))/4 * quant_col2;
if(i < q){
if(i == half) {
return value;
}
}
if(i == q - 1){
half = half + quant_col2;
q = q + quant_col2;
value = value + 12;
return cy;
}
return cy;
});
console.log($(this).val());
});
How can it be done to make it curve and the circles be positioned correctly? I appreciate your help.
edit 1: Code without data parameter
var curva = svg.selectAll("circle")
.attr("cx", function(d,i) {
var cx = $(this).attr("cx");
return p_parab.x(cx);
})
.attr("cy", function(d,i) {
var cy = $(this).attr("cy");
return p_parab.y(cy) + 15* cy;
});
Upvotes: 2
Views: 1040
Reputation: 108512
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>
Upvotes: 2
Reputation: 3562
I am definitely not sure if I understand your question, but if you are trying to position circles along a curve, I would suggest...
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>
Upvotes: 2