block by harrystevens b212d3166a85aecb9d5fc61cf660de23

Angle Between Points

Full Screen

Calculate the angle of a line with Geometric.js.

index.html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <style>
    body {
      margin: 0;
      font-family: "Helvetica Neue", sans-serif;
    }
    div {
      background: rgba(255, 255, 255, .8);
      font-size: 30px;
      padding: 10px;
      pointer-events: none;
      position: absolute;
    }
    .instruction {
      pointer-events: none;
      text-anchor: middle;
    }
    .arc {
      fill-opacity: .1;
      stroke-opacity: .1;
      stroke: #000;
      pointer-events: none;
    }
    .arc.selected {
      fill: steelblue;
      stroke: steelblue;
    }
    .baseline {
      display: none;
      stroke-dasharray: 5, 5;
      stroke: #000;
    }
    .triangle {
      cursor: move;
      fill: black;
    }
    .connector {
      pointer-events: none;
      stroke: black;
      stroke-width: 5px;
    }
    .triangle.selected {
      fill: steelblue;
    }
    .connector.selected {
      stroke: steelblue;
    }
  </style>
</head>
<body>
  <div><span>90.0</span>°</div>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script src="https://unpkg.com/geometric@1.0.0/build/geometric.min.js"></script>
  <script>
    var dragged = 0;

    var width = 960, height = 500, center = [width / 2, height / 2], arrow_position = [center[0], center[1] / 2]
    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

    svg.append("line")
        .attr("class", "baseline")
        .attr("x2", width)
        .attr("y1", center[1])
        .attr("y2", center[1]);
    var arc = svg.append("path")
        .attr("class", "arc")
        .attr("d", drawArc([center[0] + geometric.lineLength([center, arrow_position]), center[1]], arrow_position));
    var triangle = svg.append("polygon")
        .attr("class", "triangle")
        .attr("points", "-15,10 0,-10 15,10")
        .attr("transform", "translate(" + arrow_position + ")");
    var connector = svg.append("line")
        .attr("class", "connector")
        .attr("x1", center[0])
        .attr("y1", center[1])
        .attr("x2", center[0])
        .attr("y2", center[1] / 2);
    var text = svg.append("text")
        .attr("class", "instruction")
        .attr("transform", "translate(" + arrow_position + ")")
        .attr("dy", -25)
        .text("Drag the arrow");
    svg.append("circle")
        .attr("r", 5)
        .attr("transform", "translate(" + center + ")");
    
    var drag_generator = d3.drag()
      .on("start", start)
      .on("drag", drag)
      .on("end", end);

    triangle.call(drag_generator);

    function start(){
      triangle.classed("selected", 1);
      connector.classed("selected", 1);
      arc.classed("selected", 1);
      if (!dragged){
        text.transition().style("opacity", 1e-6).remove();
        dragged = 1;  
      } 
    }
    function drag(){
      arrow_position = [event.pageX, event.pageY];
      var angle = geometric.lineAngle([center, arrow_position]);
      d3.select("span").text((angle * -1).toFixed(1));

      triangle.attr("transform", "translate(" + arrow_position + ") rotate(" + (angle + 90) + ")");
      connector.attr("x2", arrow_position[0]).attr("y2", arrow_position[1]);
      arc.attr("d", drawArc([center[0] + geometric.lineLength([center, arrow_position]), center[1]], arrow_position, angle * -1));
    }
    function end(){
      triangle.classed("selected", 0);
      connector.classed("selected", 0); 
      arc.classed("selected", 0); 
    }

    function drawArc(a, b, angle){
      var d = geometric.lineLength([a, b]);
      return "M" + (angle < 0 ? a : b) + "A" + d + "," + d + " 0 0,1 " + (angle < 0 ? b : a) + " L" + center + " Z";
    }
  </script>
</body>
</html>