Pure Javascript drawing a triangle, positioning hy

2019-04-14 09:21发布

问题:

I have 3 x,y points that I am trying to use to draw a right trangle. So I am calculating the angles of the triangle after calculating side lengths. After I have gotten the hypotenuse's length, I want to rotate the hypotenuse so that it completes the triangle. For some reason, my hypotenuse is a bit out of position even though it is rotated the appropriate amount of degrees. Here is my code and a jsfiddle.

http://jsfiddle.net/kn5zk54c/

<html>
<head>
<script>

window.onload = function() {
//drawTriangle(1,1,100,1,100,100);
drawTriangle(1,1,100,1,1,100);
}


function drawTriangle(x1, y1, x2, y2, x3, y3) {

//The length of side a is the difference between point 1 and point 2's x (horizonal) axis.
var a = Math.abs(x1 - x2);

//The length of side b is the difference between point 2 and point 3's y (veritcal axis)
var b = Math.abs(y2 - y3);

//Too find the length of the last side c, we must use the pythagorean theorem.
//c*c=a*a+b*b
//square side a and b, and add the result.  Then find the square root of the result.
var c = Math.sqrt(((a*a) + (b*b)));

//We must use the Cosine rule to solve the triangles 3 angles.
//c^2 = a^2 + b^2 - c^2 

var A = (Math.acos(((c*c)+(b*b)-(a*a))/(2*c*b)))*(180/Math.PI);
var B = (Math.acos(((c*c)+(a*a)-(b*b))/(2*a*c)))*(180/Math.PI); 
var C = (Math.acos(((a*a)+(b*b)-(c*c))/(2*a*b)))*(180/Math.PI);


//Add side A div between points x1,y1, and x2,y2
var div = document.createElement('div');
div.style.height = '1px';
div.style.width = a + 'px';
div.style.backgroundColor = 'black';
div.style.position = "absolute";
div.style.left = x1;
div.style.top = y1;
document.body.appendChild(div);

//Add side B div between points x2,y2 and x3,y3
div = document.createElement('div');
div.style.height = b + "px";
div.style.width = "1px";
div.style.backgroundColor = 'black';
div.style.position = "absolute";
div.style.left = x2;
div.style.top = y2;
document.body.appendChild(div);

div = document.createElement('div');
div.style.height = "1px";
div.style.width = c + "px";
div.style.backgroundColor = 'black';
div.style.position = "absolute";
div.style.left = x3;
div.style.top = y3;

div.style.transform = "rotate(45deg)";

document.body.appendChild(div);

}

</script>
</head>
<body>
</body>
</html>

回答1:

So as @epascarello commented the top and left are not being taken into account so first thing is to add "px" to the values there, this breaks the triangle though so in the example below I have restructured what the top and left are being set as, the first two lines come form the same point(x1 y1) the last comes from the end of line 2 (x2 y2). To get the angle right over rotate it to 135deg and set the transformation origin as 0px 0px so that it then rotates in to the right place.

Having said all this you would find more consistent results using something like canvas.

EDIT actually just realised the triangle is the wrong way round as the last point is 100,100. (was trying to make it look like the one from your fiddle and ignoring what the points were saying, updated the example below so each line uses the correct points and over rotated the last to 225deg)

window.onload = function() {
  drawTriangle(1, 1, 100, 1, 100, 100);
}


function drawTriangle(x1, y1, x2, y2, x3, y3) {

  //The length of side a is the difference between point 1 and point 2's x (horizonal) axis.
  var a = Math.abs(x1 - x2);

  //The length of side b is the difference between point 2 and point 3's y (veritcal axis)
  var b = Math.abs(y2 - y3);

  //Too find the length of the last side c, we must use the pythagorean theorem.
  //c*c=a*a+b*b
  //square side a and b, and add the result.  Then find the square root of the result.
  var c = Math.sqrt(((a * a) + (b * b)));

  //We must use the Cosine rule to solve the triangles 3 angles.
  //c^2 = a^2 + b^2 - c^2 

  var A = (Math.acos(((c * c) + (b * b) - (a * a)) / (2 * c * b))) * (180 / Math.PI);
  var B = (Math.acos(((c * c) + (a * a) - (b * b)) / (2 * a * c))) * (180 / Math.PI);
  var C = (Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b))) * (180 / Math.PI);


  //Add side a.
  var div = document.createElement('div');
  div.style.height = '1px';
  div.style.width = a + 'px';
  div.style.backgroundColor = 'black';
  div.style.position = "absolute";
  div.style.left = x1 + "px";
  div.style.top = y1 + "px";
  document.body.appendChild(div);

  //Add side b.
  div = document.createElement('div');
  div.style.height = b + "px";
  div.style.width = "1px";
  div.style.backgroundColor = 'black';
  div.style.position = "absolute";
  div.style.left = x2 + "px";
  div.style.top = y2 + "px";
  document.body.appendChild(div);
  //Add side c.
  div = document.createElement('div');
  div.style.height = "1px";
  div.style.width = c + "px";
  div.style.backgroundColor = 'black';
  div.style.position = "absolute";
  div.style.left = x3 + "px";
  div.style.top = y3 + "px";
  div.style.transform = "rotate(225deg)";
  div.style.transformOrigin = "0px 0px";

  document.body.appendChild(div);

}



回答2:

Here's one way to create any kind of triangles using DIVs and transform rotate():

function drawLine (p1, p2, stroke, color) {
    var dx = p2[0] - p1[0], // Horizontal distance
        dy = p2[1] - p1[1], // Vertical distance
        angle = Math.atan2(dy, dx) * (180 / Math.PI), // Angle related to X-axis
        length = Math.sqrt(dx * dx + dy * dy), // Line length
        div = document.createElement('div');
    div.style.position = "absolute";
    div.style.left = p1[0] + 'px'; // Set position to p1 using
    div.style.top = p1[1] - stroke / 2 + 'px'; // line weight correction
    div.style.width = length + 'px'; // width as line length
    div.style.height = stroke + 'px'; // height as line weight
    div.style.background = color;
    div.style.transformOrigin = '0% 50%'; // Set origin to 50% of line weight
    div.style.transform = 'rotate(' + angle + 'deg)';
    document.body.appendChild(div);
}

function drawTriangle (P1, P2, P3, stroke, color) {
    drawLine(P1, P2, stroke, color);
    drawLine(P2, P3, stroke, color);
    drawLine(P3, P1, stroke, color);
}

drawTriangle([10, 100], [60, 10], [110, 100], 10, 'rgba(255,0,0,0.5)');
drawTriangle([120, 10], [220, 10], [170, 100], 10, 'rgba(255,0,0,0.5)');
drawTriangle([100, 150], [200, 200], [150, 300], 1, '#000000');

A correct answer to the question "Where to set the transform-origin" is 0% 50%. This is easy to find out, when creating triangles with a line weight and semi-transparent color.

You can use drawLine to draw for example rectangles or circles too.