gpt4 book ai didi

javascript - 如何从中心圆的顶部开始围绕中心圆绘制 x 个圆?

转载 作者:行者123 更新时间:2023-11-28 15:44:38 25 4
gpt4 key购买 nike

我正在尝试创建一个包含许多圆圈项目的用户界面。有时,这些圆圈周围会显示相关的圆圈。

我能够拼凑出一些有用的东西,here

问题是外圆从接近 0 度开始,我希望它们以函数/库的使用者提供的 Angular 开始。我从来都不是三 Angular 学或几何方面的明星,所以我需要一些帮助。

正如您在使用代码中看到的,有一个设置:startingDegree: 270,函数 getPosition 应该遵循该设置,但我无法弄清楚知道如何。

2014 年 4 月 2 日更新:

正如我在对 Salix alba 的评论中提到的,上面我并不清楚,但我需要的是能够指定卫星圈的半径,并让它们仅部分地环绕。 Salix 给出了一个解决方案,可以计算卫星均匀地围绕中心圆所需的尺寸。

使用 Salix 答案中的一些提示,我能够达到预期的结果......并且在未来感谢 Salix,并拥有一个额外的“模式”。

虽然仍然很粗糙,但有效的解决方案在这里:http://jsfiddle.net/RD4RZ/11/ 。这是完整的代码(只是这样):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.1.js"></script>
<style type="text/css">
.circle
{
position: absolute;
width: 100px;
height: 100px;
background-repeat: no-repeat;background-position: center center;
border: 80px solid #a19084;

border-radius: 50%;

-moz-border-radius: 50%;

}
.sm
{
border: 2px solid #a19084;

}
</style>
<script type="text/javascript">//<![CDATA[
$(function () {
function sind(x) {
return Math.sin(x * Math.PI / 180);
}

/*the law of cosines:

cc = aa + bb - 2ab cos(C), where c is the satellite diameter a and b are the legs

solving for cos C, cos C = ( aa + bb - cc ) / 2ab

Math.acos((a * a + b * b - c * c) / (2 * a * b)) = C
*/
function solveAngle(a, b, c) { // Returns angle C using law of cosines
var temp = (a * a + b * b - c * c) / (2 * a * b);
if (temp >= -1 && temp <= 1)
return radToDeg(Math.acos(temp));
else
throw "No solution";
}

function radToDeg(x) {
return x / Math.PI * 180;
}

function degToRad(x) {
return x * (Math.PI / 180);
}

var satellite = {
//settings must have: collection (array), itemDiameter (number), minCenterDiameter (number), center (json with x, y numbers)
//optional: itemPadding (number), evenDistribution (boolean), centerPadding (boolean), noOverLap (boolean)
getPosition: function (settings) {
//backwards compat
settings.centerPadding = settings.centerPadding || settings.itemPadding;
settings.noOverLap = typeof settings.noOverLap == 'undefined' ? true : settings.noOverLap;
settings.startingDegree = settings.startingDegree || 270;
settings.startSatellitesOnEdge = typeof settings.startSatellitesOnEdge == 'undefined' ? true : settings.startSatellitesOnEdge;

var itemIndex = $.inArray(settings.item, settings.collection);
var itemCnt = settings.collection.length;
var satelliteSide = settings.itemDiameter + (settings.itemSeparation || 0) + (settings.itemPadding || 0);
var evenDistribution = typeof settings.evenDistribution == 'undefined' ? true : settings.evenDistribution;
var degreeOfSeparation = (360 / itemCnt);
/*
we know all three sides:
one side is the diameter of the satellite itself (plus any padding). the other two
are the parent radius + the radius of the satellite itself (plus any padding).

given that, we need to find the angle of separation using the law of cosines (solveAngle)
*/
//if (!evenDistribution) {
var side1 = ((satelliteSide / 2)) + ((settings.minCenterDiameter + (2 * settings.centerPadding)) / 2);
var side2 = satelliteSide;;


var degreeOfSeparationBasedOnSatellite = solveAngle(side1, side1, side2); //Math.acos(((((side1 * side1) + (side2 * side2)) - (side2 * side2)) / (side2 * side2 * 2)) / 180 * Math.PI) * Math.PI;
degreeOfSeparation = evenDistribution? degreeOfSeparation: settings.noOverLap ? Math.min(degreeOfSeparation, degreeOfSeparationBasedOnSatellite) : degreeOfSeparationBasedOnSatellite;

//}
//angle-angle-side
//a-A-B
var a = satelliteSide;
var A = degreeOfSeparation;
/*
the three angles of any triangle add up to 180. We know one angle (degreeOfSeparation)
and we know the other two are equivalent to each other, so...
*/
var B = (180 - A) / 2;

//b is length necessary to fit all satellites, might be too short to be outside of base circle
var b = a * sind(B) / sind(A);

var offset = (settings.itemDiameter / 2) + (settings.itemPadding || 0); // 1; //
var onBaseCircleLegLength = ((settings.minCenterDiameter / 2) + settings.centerPadding) + offset;

var offBase = false;

if (b > onBaseCircleLegLength) {
offBase = true;
}

b = settings.noOverLap ? Math.max(b, onBaseCircleLegLength) : onBaseCircleLegLength;

var radianDegree = degToRad(degreeOfSeparation);
//log('b=' + b);
//log('settings.center.x=' + settings.center.x);
//log('settings.center.y=' + settings.center.y);

var degreeOffset = settings.startingDegree;
if (settings.startSatellitesOnEdge) {
degreeOffset += ((offBase ? degreeOfSeparation : degreeOfSeparationBasedOnSatellite) / 2);
}

var i = ((Math.PI * degreeOffset) / 180) + (radianDegree * itemIndex);// + (degToRad(degreeOfSeparationBasedOnSatellite) / 2); //(radianDegree) * (itemIndex);
var x = (Math.cos(i) * b) + (settings.center.x - offset);
var y = (Math.sin(i) * b) + (settings.center.y - offset);

return { 'x': Math.round(x), 'y': Math.round(y) };
}
,
/* if we ever want to size satellite by how many need to fit tight around the base circle:

x: function calcCircles(n) {
circles.splice(0); // clear out old circles
var angle = Math.PI / n;
var s = Math.sin(angle);
var r = baseRadius * s / (1 - s);
console.log(angle);
console.log(s);
console.log(r);
console.log(startAngle);
console.log(startAngle / (Math.PI * 2));
for (var i = 0; i < n; ++i) {
var phi = ((Math.PI * startAngle) / 180) + (angle * i * 2);
var cx = 150 + (baseRadius + r) * Math.cos(phi);
var cy = 150 + (baseRadius + r) * Math.sin(phi);
circles.push(new Circle(cx, cy, r));
}
},
*/
//settings must have: collection (array), itemDiameter (number), minCenterDiameter (number), center (json with x, y numbers)
//optional: itemPadding (number), evenDistribution (boolean), centerPadding (boolean), noOverLap (boolean)
getAllPositions: function (settings) {
var point;
var points = [];
var collection = settings.collection;

for (var i = 0; i < collection.length; i++) {

settings.item = collection[i]

points.push(satellite.getPosition(settings));
}
return points;
}
};
var el = $("#center"), cnt = 10, arr = [], itemDiameter= 100;

for (var c = 0; c < cnt; c++) {
arr.push(c);
}



var settings = {
collection: arr,
itemDiameter: itemDiameter,
minCenterDiameter: el.width(),
center: { x: el.width() / 2, y: el.width() / 2 },
itemPadding: 2,
evenDistribution: false,
centerPadding: parseInt(el.css("border-width")),
noOverLap: false,
startingDegree: 270
};
var points = satellite.getAllPositions(settings);

for (var i = 0; i < points.length; i++) {
var $newdiv1 = $("<div></div>");
var div = el.append($newdiv1);
$newdiv1.addClass("circle").addClass("sm");
$newdiv1.text(i);
$newdiv1.css({ left: points[i].x, top: points[i].y, width: itemDiameter +'px', height: itemDiameter +'px' });
}
});//]]>

</script>
</head>
<body>
<div id="center" class="circle" style="left:250px;top:250px" >
</div>
</body>
</html>

最佳答案

您需要计算的中心位是小圆圈的半径。如果您有 R 作为中心圆的半径,并且您想在其周围放置 n 个较小的圆。令小圆的未知半径为r。我们可以构造一个直 Angular 三 Angular 形,其中一个 Angular 在大圆的中心,一个 Angular 在小圆的中心,一个 Angular 在中心的一条线与小圆的相切处。这将是一个直 Angular 。中心的 Angular 是a,斜边的长度是R+r,相反的 Angular 是r,我们不需要相邻的。使用三 Angular 函数

sin(a) = op / hyp = r / (R + r)

重新排列

(R+r) sin(a) = r
R sin(a) + r sin(a) = r
R sin(a) = r - r sin(a)
R sin(a) = (1 - sin(a)) r
r = R sin(a) / ( 1 - sin(a))

一旦我们有了r,我们就差不多完成了。

您可以将其视为 fiddle http://jsfiddle.net/SalixAlba/7mAAS/

// canvas and mousedown related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();

// save canvas size to vars b/ they're used often
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var baseRadius = 50;
var baseCircle = new Circle(150,150,50);

var nCircles = 7;
var startAngle = 15.0;

function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
}

Circle.prototype.draw = function() {
ctx.beginPath();
ctx.arc(this.x,this.y,this.r, 0, 2 * Math.PI, false);
ctx.stroke();
}

var circles = new Array();

function calcCircles(n) {
circles.splice(0); // clear out old circles
var angle = Math.PI / n;
var s = Math.sin(angle);
var r = baseRadius * s / (1-s);
console.log(angle);
console.log(s);
console.log(r);


for(var i=0;i<n;++i) {
var phi = startAngle + angle * i * 2;
var cx = 150+(baseRadius + r) * Math.cos(phi);
var cy = 150+(baseRadius + r) * Math.sin(phi);
circles.push(new Circle(cx,cy,r));
}
}

function draw() {
baseCircle.draw();
circles.forEach(function(ele){ele.draw()});
}

calcCircles(7);
draw();

关于javascript - 如何从中心圆的顶部开始围绕中心圆绘制 x 个圆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22779068/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com