答案 0 :(得分:7)
您正在绘制多个圈子
功能:编写可重用代码的有效方法!
您可以创建可重复使用的函数,而不是重写(重复)代码来绘制您的2种类型的圆圈,这些函数可以获取特定于圆圈的变量,并使用这些变量来绘制您的描边或实心圆圈。
描绘您的轨道的功能
drawOrbit
函数接受半径并在中心点周围的半径处描边圆圈:
// cx,cy is the concentric centerpoint of your orbits -- cx,cy don't change
// radius is how far your orbit is from the centerpoint -- radius does change
function drawOrbit(radius){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.stroke();
}
绘制轨道体(圆圈)的功能
circleInOrbit
函数接受半径并在中心点周围的半径处描边圆圈:
x,y
使用三角函数计算。cx,cy
是轨道中心点orbits[circle.orbitIndex]
从轨道阵列中获取轨道对象。然后轨道对象告诉函数离轨道中心点有多远。Math.cos(angle) & Math.sin(angle)
告诉函数在轨道圆周上的轨道圆是 drawOrbitingCircle
函数如下所示:
// Takes in a circle object that holds the circle's orbit & rotation angle
// It draws the orbiting circle on the specified orbit at the specified angle
function drawOrbitingCircle(circle){
var x=cx+orbits[circle.orbitIndex]*Math.cos(circle.angle);
var y=cy+orbits[circle.orbitIndex]*Math.sin(circle.angle);
ctx.beginPath();
ctx.arc(x,y,circleRadius,0,Math.PI*2);
ctx.fillStyle='lightgray';
ctx.fill();
ctx.strokeStyle='white';
ctx.stroke();
}
[添加:显示签名中心圈&防止重叠圆圈]
此功能绘制一个包含文字符号(加号)的蓝色圆圈:
请注意,您可以将文字对齐为水平居中&垂直与context.textAlign = 'center'
和context.textBaseline = 'middle'
。
function drawSignedCenterCircle(signCharacter){
ctx.beginPath();
ctx.arc(cx,cy, 18, 0, 2 * Math.PI);
ctx.fillStyle='blue';
ctx.fill();
ctx.fillStyle='white';
ctx.font='24px verdana';
ctx.textAlign='center';
ctx.textBaseline='middle';
ctx.fillText(signCharacter,cx,cy);
}
此代码会创建不会重叠的轨道圆。
它的工作原理是为每个轨道圆提供一个独特的轨道切片。由于每个切片都是唯一的,因此任何圆圈都不会与同一轨道上的任何其他圆重叠。
// calculate non-overlapping placements of orbiting bodies
for(var o=0;o<orbits.length;o++){
var count=circleCountByOrbit[o];
var sweep=Math.PI*2/count;
for(var c=0;c<count;c++){
var midAngle=(sweep*c)+sweep/2;
var randomOffset=Math.random()*0.50-1;
var angle=midAngle+sweep*randomOffset;
circles.push({orbitIndex:o, angle:angle});
}
}
示例代码和演示:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
$("#canvas").mousedown(function(e){handleMouseDown(e);});
var cx=cw/2;
var cy=ch/2;
var circleRadius=10;
var blueRadius=18;
var orbits=[40,80,120];
var circleCountByOrbit=[3,5,7];
var circles=[];
// calculate non-overlapping placements of orbiting bodies
for(var o=0;o<orbits.length;o++){
var count=circleCountByOrbit[o];
var sweep=Math.PI*2/count;
for(var c=0;c<count;c++){
var midAngle=(sweep*c)+sweep/2;
var randomOffset=Math.random()*0.50-1;
var angle=midAngle+sweep*randomOffset;
var x=cx+orbits[o]*Math.cos(angle);
var y=cy+orbits[o]*Math.sin(angle);
circles.push({
cx:x, cy:y,
radius:circleRadius,
orbitIndex:o,
angle:angle
});
}
}
// draw the stroked orbits
for(var i=0;i<orbits.length;i++){
drawOrbit(orbits[i]);
}
// draw the orbiting bodies
for(var i=0;i<circles.length;i++){
drawOrbitingCircle(circles[i]);
}
// draw the signedCenterCircle
drawSignedCenterCircle('+');
function drawOrbit(radius){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.stroke();
}
function drawOrbitingCircle(circle){
x=circle.cx;
y=circle.cy;
ctx.beginPath();
ctx.arc(x,y,circleRadius,0,Math.PI*2);
ctx.fillStyle='lightgray';
ctx.fill();
ctx.strokeStyle='white';
ctx.stroke();
}
function drawSignedCenterCircle(signCharacter){
ctx.beginPath();
ctx.arc(cx,cy, blueRadius, 0, 2 * Math.PI);
ctx.fillStyle='blue';
ctx.fill();
ctx.fillStyle='white';
ctx.font='24px verdana';
ctx.textAlign='center';
ctx.textBaseline='middle';
ctx.fillText(signCharacter,cx,cy);
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Check if mouse is inside any orbiting circle
for(var i=0;i<circles.length;i++){
var c=circles[i];
var dx=mouseX-c.cx;
var dy=mouseY-c.cy;
if(dx*dx+dy*dy<c.radius*c.radius){
drawOrbitingCircle(circles[i]);
ctx.fillStyle='red';
ctx.fill();
}
}
// Check if mouse is inside any orbiting circle
var dx=mouseX-cx;
var dy=mouseY-cy;
if(dx*dx+dy*dy<blueRadius*blueRadius){
alert('You clicked in blue circle');
}
}
&#13;
body{ background-color:white;padding:20px;}
#canvas{border:1px solid red; margin:0 auto; }
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Click in a circle.</h4>
<canvas id="canvas" width=300 height=300></canvas>
&#13;