我有一系列项目,我想放在同心圆上。见图。我在数学方面遇到了麻烦。
我可以计算“步数”变量(每个项目是40x40,所以步长是圆周除以宽度加上边距)。我可以计算给定半径和步长的点,但我不知道如何根据当前项目索引计算半径。
for(var i = 0; i < items.length; i++) {
var radius = functionOf(i)??;
var steps = Math.floor((2*radius*Math.PI)/60);
var x = Math.floor(0 + radius * Math.cos(2 * Math.PI * index / steps));
var y = Math.floor(0 + radius * Math.sin(2 * Math.PI * index / steps));
//draw item at x,y
}
关于如何计算半径作为i函数的思考?
答案 0 :(得分:0)
您可以使用算术级数的总和来计算每个项目的半径(对于等距离的圆形项目形成该级数),但是有更简单和更快的方法 - 圆形填充后的更改半径(伪代码)
var radius = 0;
var i = 0;
while (i < items.length) {
var steps = Math.floor((2*radius*Math.PI)/60);
for(var index = 0; index < steps; index++) {
var x = Math.floor(0 + radius * Math.cos(2 * Math.PI * index / steps));
var y = Math.floor(0 + radius * Math.sin(2 * Math.PI * index / steps));
//draw item at x,y
i++;
if (i == items.length)
break;
}
radius = radius + 60; //start next circle
}
关于arithmetic progression:
对于第一个项目a0的进展和差异d,前n个成员的总和是
S = n * (2 * a0 + d * (n - 1)) / 2
所以为了找到某个索引S
所属的圈子,我们必须解决二次不等式(找到最大整数x来满足条件)
x^2 * d + x * (2 * a0 - d) - 2 * S <= 0
在Delphi中检查解决方案:
function GetCircle(a0, d, i: Integer): Integer;
var
Discr: Double;
begin
Discr := (2 * a0 - d) * (2 * a0 - d) + 8 * i * d;
if Discr < 0 then
Exit(0);
Result := Floor((d - 2 * a0 + Sqrt(Discr)) / (2 * d));
end;
对于案例a0 = 1,d = 6(你的图片有点不同 - 进展不准确)它给出了
i=0: 0
i=1..7: 1
i=8..20: 2
i=21..39: 3
and so on
这意味着:
第0项位于半径为0的圆上
半径为1 * R
的圆的第3项
圆形的第11项,半径为2 * R
...
答案 1 :(得分:0)
鉴于你的样本图像,一个简单的方法是为每个外圈添加6个元素,这样我们就可以得到序列:1,6,12,18 ......
然后每个圆的半径可以放大一个恒定的量,大于元素大小:
// center of the circles
var centerx = 350;
var centery = 350;
// start drawing the central (first) element
if ( items.length > 0 ) {
// draw item at centerx, centery
}
var k = 1;
var i = 1;
while ( i < items.length ) {
// number of elements on this circle
var steps = k * 6;
// angular distance between elements
var angle_range = 2 * Math.PI / steps;
// every circle is bigger then the previuos of the same amount
var radius = k * 60;
var j = 0;
while ( j < steps && i < items.length ) {
var angle = j * angle_range;
var x = Math.round(centerx + radius * Math.cos(angle));
var y = Math.round(centery + radius * Math.sin(angle));
//draw item at x,y
i++;
j++;
}
k++;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Circles</title>
<link href="stile.css"/>
</head>
<body>
<canvas id="myCanvas" width="700" height="700" style="border:1px solid #000000;">
</canvas>
<script>
// dummy draw function
function draw_item( itm, cntx, x, y) {
cntx.fillStyle = "#0022FF";
cntx.fillRect(x - 20, y - 20, 40, 40);
cntx.font = "14px Arial";
cntx.fillStyle = "#FFFFFF";
cntx.fillText(itm, x - 7, y + 5);
}
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// dummy array
var items = [];
for ( var i = 0; i < 91; i++ ) {
items.push(i);
}
// center of the circles
var centerx = 350;
var centery = 350;
// start drawing the central (first) element
if ( items.length > 0 ) {
draw_item(items[0], ctx, centerx, centery);
}
var k = 1;
var i = 1;
while ( i < items.length ) {
// number of elements on this circle
var steps = k * 6;
// angular distance between elements
var angle_range = 2 * Math.PI / steps;
// every circle is bigger then the previuos of the same amount
var radius = k * 60;
var j = 0;
while ( j < steps && i < items.length ) {
var angle = j * angle_range;
var x = Math.round(centerx + radius * Math.cos(angle));
var y = Math.round(centery + radius * Math.sin(angle));
//draw item at x,y
draw_item(items[i], ctx, x, y);
i++;
j++;
}
k++;
}
</script>
</body>
</html>