block by harrystevens e452d8c4210926d3a162162ec41b7f55

Arc Path

Full Screen

Draw an arc path between two points. Drag the points to see the arc adapt.

index.html

<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      margin: 0;
    }
    .circle {
      cursor: move;
    }
    .circle.selected {
      fill: tomato;
      stroke: black;
    }
  </style>
</head>
<body>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script>
    var width = window.innerWidth,
        height = window.innerHeight,
        radius = 15;

    var data = [[100, 100], [width - 100, height - 100]];
    
    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

    var arc = svg.append("path")
        .style("fill", "none")
        .style("stroke", "black")
        .attr("d", drawArc(data));  

    var circles = svg.selectAll("circle")
        .data(data)
      .enter().append("circle")
        .attr("class", (d, i) => "circle circle-" + i)
        .attr("r", radius)
        .attr("transform", d => "translate(" + d + ")")
        .call(d3.drag()
          .on("start", dragStart)
          .on("drag", dragging)
          .on("end", dragEnd)
        );

    function dragStart(d, i){
      d3.select(".circle-" + i).classed("selected", 1);
    }
    function dragging(d, i){
      data[i] = [
        event.pageX < radius ? radius : event.pageX > width - radius ? width - radius : event.pageX,
        event.pageY < radius ? radius : event.pageY > height - radius ? height - radius : event.pageY
      ];
      d3.select(".circle-" + i).attr("transform", "translate(" + data[i] + ")");
      arc.attr("d", drawArc(data)); 
    }
    function dragEnd(d, i){
      d3.select(".circle-" + i).classed("selected", 0);
    }

    // The argument "d" is an array of two points, where each point is an array of two coordinates
    function drawArc(d){
      var dx = d[1][0] - d[0][0],
          dy = d[1][1] - d[0][1],
          dr = Math.sqrt(dx * dx + dy * dy) * .67; // Reduce for more bend

      return "M" + d[0][0] + "," + d[0][1] + "A" + dr + "," + dr + " 0 0,1 " + d[1][0] + "," + d[1][1];      
    }

    window.onresize = _ => {
      width = window.innerWidth;
      height = window.innerHeight;

      svg
        .attr("width", width)
        .attr("height", height);

      circles
        .attr("transform", (d, i, e) => {
          var curr_transform = d3.select(e[i]).attr("transform").replace("translate(", "").replace(")", "").split(",").map(d => +d);
          data[i] = [
            curr_transform[0] > width - radius ? width - radius : curr_transform[0],
            curr_transform[1] > height - radius ? height - radius : curr_transform[1]
          ];
          arc.attr("d", drawArc(data));
          return "translate(" + data[i] + ")";
        });
    }
  </script>
</body>
</html>