jack blank
jack blank

Reputation: 5195

Rotating a line around a circle

I have two arcs with strokes and i want to have a line animate between them. The line should animate perpendicular to the points of the inner circle.

Here's something that I hacked together that is almost what I want.

things that are wrong with it are:

I had problem understanding how to use the trig function for lineTo. maybe because that changes the length of the line and I didn't know how to get the x and y coordinates of the outer circle to get the end point of the line. I'm used to doing math.cos * length and this gives me a line at an angle. I don't what a line I just wanted the coords of the outer circle.

window.onload = function(){
	var canvas = document.getElementById("canvas");
	var context = canvas.getContext("2d");
	function lineAtAngle(startX, startY, angleDeg, length, startX2, startY2, angleDeg2, length2){
			var angle = angleDeg * (Math.PI / 180);
			var angle2 = angleDeg2 * (Math.PI / 180);
			// context.moveTo(startX, startY);
			context.beginPath();
			context.moveTo(
				Math.cos(angle) * length + startX,
				Math.sin(angle) * length + startY
				)
			 context.lineTo(
				Math.cos(angle2) *(length2 )+ startX2,
				Math.sin(angle2)  *(length2) + startY2
				)
			// context.lineTo(canvas.width / 2 + 60, canvas.height / 2, angle2, length2)
			
			context.lineWidth = 10;
			context.stroke();
			context.closePath();
			console.log("startX2: " + startX2 + " startY2: " + startY2 )
			console.log(Math.sin(angle2) + startY2)
			console.log(length)
	}
	function myLineTo(startX, startY, angleDeg, length){

	}
	var length1 = canvas.width / 2 + 60 - canvas.width / 2 -30
	var length2 = canvas.width / 2 ;
	// var length2 = 1;
	console.log(length2)
	var angle1 = 0;
	var angle2 = 0;
	(function animate(){
		context.clearRect(0,0, canvas.width, canvas.height);
		window.requestAnimationFrame(animate);	
		context.beginPath()
		context.arc(canvas.width / 2, canvas.height / 2, 30, 0, 2 * Math.PI, true)
		context.lineWidth = 1;
		context.stroke()

		context.beginPath();
		context.arc(canvas.width / 2, canvas.height / 2, 60, 0, 2 * Math.PI, true);
		context.stroke();
		context.closePath()

		context.beginPath();
		context.arc(canvas.width / 2, canvas.height / 2, 3, 0, 2 * Math.PI, true)
		context.fill()
		context.closePath();
		angle1++
		angle2++
		// lineAtAngle(canvas.width / 2 , canvas.height / 2 , angle1, length1, canvas.width / 2 + 60, canvas.height / 2, angle2, length2 )
		lineAtAngle(canvas.width / 2 , canvas.height / 2 , angle1, length1, canvas.width / 2 + 60, canvas.height / 2, angle2, length2 )




	}())

}
		canvas{
			background: #aaa;
		}
<canvas id="canvas" width="400" height="400"></canvas>

Upvotes: 2

Views: 2777

Answers (2)

Alnitak
Alnitak

Reputation: 339816

I believe the below is what you're trying to achieve.

I've simplified the code somewhat by using the Canvas's built-in methods to translate the coordinate space to the center and by removing the extra function which had way too many parameters passed when all it needed was one angle and two radii.

window.onload = function(){
	var canvas = document.getElementById("canvas");
	var context = canvas.getContext("2d");

	var radius1 = 30;
	var radius2 = 60;
	var angle = 0;

	(function animate(){
		context.clearRect(0, 0, canvas.width, canvas.height);

		// save state and adjust coordinate space
		context.save();
		context.translate(canvas.width / 2, canvas.height / 2);

		context.lineWidth = 1;

		context.beginPath()
		context.arc(0, 0, radius1, 0, 2 * Math.PI, true)
		context.stroke()

		context.beginPath();
		context.arc(0, 0, radius2, 0, 2 * Math.PI, true);
		context.stroke();

		context.beginPath();
		context.arc(0, 0, 3, 0, 2 * Math.PI, true);
		context.fill()

		++angle;
		var rads = angle * Math.PI / 180;
		var x = Math.cos(rads);
		var y = Math.sin(rads);

		context.lineWidth = 10;
		context.beginPath();
		context.moveTo(radius1 * x, radius1 * y);
		context.lineTo(radius2 * x, radius2 * y);
		context.stroke();

		// restore transformations for next pass
		context.restore();

		window.requestAnimationFrame(animate)
	}())

}
canvas { background: #aaa; }
<canvas id="canvas" width="400" height="200"></canvas>

Upvotes: 2

Steven Hansen
Steven Hansen

Reputation: 3239

The idea for drawing a line is that you need to supply a start point (moveTo), and an end point (lineTo). Your current code is complicating the whole thing with multiple angles and lengths. What you want to imagine you are doing is starting at the center of your circle, then adding an offset which places the start point at the edge of the inner circle. Using trig is perfectly fine here. The length of your line will simply be outer radius minus inner radius, in the same direction as your offset (only one angle was needed).

Without fundamentally changing your approach, the code below shows the changes you could use to try this. Have your line function take a starting point (x, y) and an offset, as well as the angle and length. The starting point is your circle center, and the offset is the radius of the inner circle. The length (again) is simply the outer radius minus the inner radius.

window.onload = function(){
   var innerCircleRadius = 30;
   var outerCircleRadius = 60;
   var canvas = document.getElementById("canvas");
   var context = canvas.getContext("2d");
   var angle1 = 0;
   function lineAtAngle(startX, startY, angleDeg, offset, length) {
      var angle = angleDeg * (Math.PI / 180); // Convert to radians.
      var cosAngle = Math.cos(angle); // Only need cos(angle) once.
      var sinAngle = Math.sin(angle); // Only need sin(angle) once.
      var startXPos = cosAngle * offset + startX; 
      var startYPos = sinAngle * offset + startY; 
      var endXPos = cosAngle * length + startXPos;
      var endYPos = sinAngle * length + startYPos;
      context.beginPath();
            
      context.moveTo(startXPos, startYPos);
      context.lineTo(endXPos, endYPos); 
			
      context.lineWidth = 10;
      context.stroke();
      context.closePath();
   }
   (function animate() {
	  context.clearRect(0,0, canvas.width, canvas.height);
	  window.requestAnimationFrame(animate);	
	  context.beginPath()
	  context.arc(canvas.width / 2, canvas.height / 2, innerCircleRadius, 0, 2 * Math.PI, true)
	  context.lineWidth = 1;
	  context.stroke()

	  context.beginPath();
	  context.arc(canvas.width / 2, canvas.height / 2, outerCircleRadius, 0, 2 * Math.PI, true);
	  context.stroke();
	  context.closePath()

	  context.beginPath();
	  context.arc(canvas.width / 2, canvas.height / 2, 3, 0, 2 * Math.PI, true)
	  context.fill()
	  context.closePath();
	  angle1++
	  lineAtAngle(canvas.width / 2 , canvas.height / 2 , angle1, innerCircleRadius, outerCircleRadius - innerCircleRadius);
   }())
}
canvas {
   background: #aaa;
}
<canvas id="canvas" width="400" height="400"></canvas>

Upvotes: 1

Related Questions