Принцип построения круга:
Учитывая центр x,y
, радиус r
, мы можем построить точки, принадлежащие окружности, вычислив их координаты следующим образом: px = x + r * Math.cos(angle)
и py = y + r * Math.sin(angle)
, когда угол изменяется от 0 до 2* Math.PI
.
Если r
увеличивается при изменении угла, мы получаем внешнюю спираль (от угла 0 до угла 2 * PI, что эквивалентно 0).
Для рассматриваемой задачи нам нужно вычислить начальное и конечное положение спирали в полярных координатах (расстояние, угол).
Поэтому нам нужно вычислить начальный угол, начальное расстояние, конечный угол и конечное расстояние и построить каждую точку, постепенно увеличивая угол и расстояние.
Первоначальный расчет тета был неверным, я изменил его.
Затем мне нужно было вычислить начальное расстояние между центром и начальной точкой, а также конечное расстояние между центром и конечной точкой.
Во время вращения вы прогрессируете от начального расстояния до конечного расстояния.
Общее угловое расстояние должно быть totalTheta = numberOfRotation * 2 * Math.PI + (endAngle - startAngle)
, я заменил rotations * Math.PI * 2
на totalTheta
)
Просто для забавы и чтобы продемонстрировать, что это работает для любых начальных условий, я немного рандомизировал начальную позицию, конечную позицию и число оборотов.
Я также уменьшил приращение угла на каждой итерации, чтобы расстояние между каждой точкой выглядело более равномерным, но вы можете оставить комментарий, чтобы сохранить постоянную угловую скорость.
Приведенное ниже решение случайным образом выберет оранжевую точку, зеленую точку, число витков для завершения спирали и построит спираль вокруг неподвижной фиолетовой точки.
var c = document.getElementById("myCanvas");
var cxt = c.getContext("2d");
//center of the spiral coords:
var centerX = 200;
var centerY = 150;
//draw the center of spiral point:
drawCirc(centerX, centerY, 10, '#6f0c4f');
var gap = 8;
var STEPS_PER_ROTATION = 50;
var rotations = 1 + parseInt(Math.random() * 5, 10);
var increment = rotations * Math.PI / STEPS_PER_ROTATION;
var theta = increment;
var dist = 0;
//start point:
var startX = centerX + (Math.random() * 150 - 75);
var startY = centerY + (Math.random() * 150 - 75);
var startAngleOffset = startX > centerX ? (startY > centerY ? 0 : 0) : (startY > centerY ? Math.PI : Math.PI);
var startAngleSign = startX > centerX ? (startY > centerY ? 1 : -1) : (startY > centerY ? -1 : 1);
//end point:
var endX = centerX + (Math.random() * 150 - 75);
var endY = centerY + (Math.random() * 150 - 75);
var endAngleOffset = endX > centerX ? (endY > centerY ? 0 : 0) : (endY > centerY ? Math.PI : Math.PI);
var endAngleSign = endX > centerX ? (endY > centerY ? 1 : -1) : (endY > centerY ? -1 : 1);
//draw the start and end points as small circles:
drawCirc(startX, startY, 6, '#FF0000');
drawCirc(endX, endY, 6, '#00FF00');
var startTheta = theta = startAngleOffset + startAngleSign * Math.atan(Math.abs(startY - centerY)/Math.abs(startX - centerX));
var endTheta = endAngleOffset + endAngleSign * Math.atan(Math.abs(endY - centerY)/Math.abs(endX - centerX));
var totalTheta = rotations * 2 * Math.PI + (endTheta - startTheta)
dist = Math.sqrt(Math.pow(startY - centerY, 2) + Math.pow(startX - centerX, 2));
finalDist = Math.sqrt(Math.pow(endY - centerY, 2) + Math.pow(endX - centerX, 2));
var ind = 0;
while (theta -startTheta < totalTheta) {
var currentDist = (dist + ((finalDist - dist)* ((theta - startTheta) / (totalTheta))));
var newX = centerX + currentDist * Math.cos(theta);
var newY = centerY + currentDist * Math.sin(theta);
var ukwObj = { x: newX, y: newY };
if (ind == 0) {
//draw start point with differnt color to differentiate
drawCirc(newX, newY, 2, 'orange');
} else {
drawCirc(newX, newY);
}
ind++;
theta = theta + increment;
// decrement increment to make the space between points look more regular
increment = Math.max(0.01, increment - 0.00096);
}
function drawCirc(x, y, radius = 2, stroke = '#000000') {
cxt.beginPath();
cxt.arc(x, y, radius, 0, 2 * Math.PI);
cxt.strokeStyle = stroke;
cxt.stroke();
cxt.fillStyle = stroke;
cxt.fill();
}
cxt.stroke(); // draw the spiral
<!DOCTYPE HTML>
<html>
<body>
<canvas id="myCanvas" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>
</body>
</html>