【问题标题】:Rotating a line around a circle绕一圈旋转一条线
【发布时间】:2015-12-25 00:06:18
【问题描述】:

我有两条带有笔划的弧线,我希望它们之间有一条线动画。这条线的动画应该垂直于内圆的点。

这是我拼凑起来的东西,几乎就是我想要的。

有以下问题:

  • 线的长度不是两个圆之间的长度,因为它围绕内圆旋转。
  • 有时这条线不垂直于内圆的点。例如,当它到达圆的角落时,它会稍微倾斜一个角度。

我无法理解如何使用lineTo 的三角函数。可能是因为这改变了线的长度,而我不知道如何获取外圆的 x 和 y 坐标来获取线的终点。我习惯于做math.cos * length,这给了我一条斜线。我不是什么线,我只想要外圈的坐标。

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>

【问题讨论】:

  • 角度问题是canvas.width / 2 + 60.

标签: javascript animation math canvas geometry


【解决方案1】:

我相信以下是您想要实现的目标。

我通过使用 Canvas 的内置方法将坐标空间转换为中心并删除了在只需要一个角度和两个半径时传递的参数过多的额外函数,从而稍微简化了代码。

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>

【讨论】:

  • 虽然您编写了良好的功能代码,但您确实没有解决 OP 做错了什么,或者如何解决他们尝试过的问题。
  • @StevenHansen 那是因为原始代码太混乱了,很难准确指出他哪里出错了。
  • 这是我试图实现的功能,感谢您的回答。但我想试验三角函数。比如圆上的访问坐标。
  • @jackblank 很好 - 我会更新以使用一些三角函数而不是旋转
  • p.s 那里有太多的“closePath”调用——只有当你想将路径中的最后一个点明确地附加到第一个点时才需要它们。
【解决方案2】:

绘制一条线的想法是您需要提供一个起点 (moveTo) 和一个终点 (lineTo)。您当前的代码使整个事情变得复杂,具有多个角度和长度。你想想象你正在做的是从你的圆的中心开始,然后添加一个偏移量,将起点放在内圆的边缘。在这里使用 trig 非常好。直线的长度就是外半径减去内半径,与偏移方向相同(只需要一个角度)。

在不从根本上改变您的方法的情况下,下面的代码显示了您可以用来尝试的更改。让您的 line 函数获取起点 (x, y) 和偏移量,以及角度和长度。起点是你的圆心,偏移量是内圆的半径。长度(再次)只是外半径减去内半径。

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>

【讨论】:

  • 我正在尝试使用 C 语言实现相同的功能。但数学不是我的一杯茶。你能推荐一些我可以学习应用三角学的资源吗?我总是找到理论,但没有应用现实生活中的例子,所以我很难实际实施它
猜你喜欢
  • 2019-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-29
相关资源
最近更新 更多