如何将svg圆圈放在一条直线上并弯曲它?

时间:2016-11-15 01:39:34

标签: javascript math d3.js svg logic

我正在制作像seat.io这样的软件,而我正试图改变圆圈的线条。我首先使用d3.js创建一个带有svg圆圈的正方形。

y坐标

我开始找到中间圆圈并将它的cy设置为0,然后将其设置为顺序(每行增加12个。然后我意识到如果它是偶数,则无法找到中间点。< / p>

我决定使用bhaskara公式来找到曲线坐标,但我仍然坚持如何将它放在循环中:

$("#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());
});

如何才能使曲线和圆圈正确定位? 感谢您的帮助。

编辑1: 没有数据参数的代码

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;
        });

2 个答案:

答案 0 :(得分:2)

我绝对不确定我是否理解你的问题,但如果你试图沿着曲线定位圆圈,我会建议......

  1. 为您想要的曲线编写等式
  2. 将该曲线转换为parametric equation
  3. 将x等式用于cx,使用y等式进行cy
  4. 参数方程将为您提供单行。对于每一个额外的行,您需要考虑该行中所有cy的附加偏移量。

    这是一个非常粗略的例子,你可以建立......

    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>

答案 1 :(得分:2)

我喜欢@ steveladavich的回答,但我会提出替代方案。您可以使用d3曲线拟合点的能力,然后将圆圈放在生成的路径上:

&#13;
&#13;
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");
&#13;
<script src="http://d3js.org/d3.v4.js"></script>
&#13;
&#13;
&#13;