献给12岁的你们!
我为你们写了一些代码,它并不无聊或有趣,也不容易或困难,但它能完成任务:
var canvas = document.getElementById('c1').getContext('2d');
var radius = 50;
var circles = [
{
color:'blue',
x : 2*radius - radius/2,
y : 2*radius,
isTop: true
} , {
color:'black',
x : 4*radius,
y : 2*radius,
isTop: true
} , {
color:'red',
x : 6*radius + radius/2,
y : 2*radius,
isTop: true
} , {
color:'yellow',
x : 3*radius - radius/4,
y : 3*radius,
isTop: false
} , {
color:'green',
x : 5*radius + radius/4,
y : 3*radius,
isTop: false
}
];
function drawArc(canvas, color, x, y, start, end) {
if (color !== 'white') drawArc(canvas, 'white', x, y, start, end);
canvas.lineWidth = color === 'white' ? 16 : 10;
canvas.strokeStyle = color;
canvas.beginPath();
canvas.arc(x, y, radius, start - Math.PI/2, end - Math.PI/2, true);
canvas.stroke();
}
circles.forEach(function(circle){
drawArc(canvas, circle.color, circle.x, circle.y, 0, Math.PI*2);
});
circles.forEach(function(circle){
if (circle.isTop) {
drawArc(canvas, circle.color, circle.x, circle.y, Math.PI, Math.PI*2/3);
drawArc(canvas, circle.color, circle.x, circle.y, Math.PI*5/3, Math.PI*4/3);
} else {
drawArc(canvas, circle.color, circle.x, circle.y, 0, Math.PI/3);
drawArc(canvas, circle.color, circle.x, circle.y, Math.PI*2/3, Math.PI/3);
}
});
http://jsbin.com/IrOJOhIg/1/edit
如果我要解释这段代码,我会从“circles”变量开始讲起,它是一个数组,用于指定每个圆的颜色、中心位置以及它是否在顶部行。我会注释掉“+= radius/2”和“radius/4”的部分,并运行代码,展示圆圈之间距离太近的结果,然后取消注释,演示改变x坐标移动它们的效果。
接下来,我会解释“drawArc”函数,该函数绘制圆的一部分,首先是白色,然后是实际颜色,线宽不同。这几乎是整个脚本中最难的部分。
最后,我会再次运行脚本,注释掉最后的forEach,展示最后绘制的环完全覆盖了先前的环,并请12岁的孩子想出解决方案。你应该试图绘制圆的一部分。
我将圆分成6个部分,从顶部开始,如果你好好看它们,你会发现如果圆在顶部行或不在顶部行,则相同的部分可以被覆盖或在顶部。最后的forEach重新绘制每个圆的2个必须在交叉点上的部分。
最后,如果12岁的孩子注意到我的代码中实际上交叉点是反向的,那么会得到额外的奖励分数;如果有人想出解决方案,也会得到更多的奖励分数。(显然,最简单的解决方案就是调整最后的forEach)。编辑:事实上,将条件设置为“!circle.isTop”更加简单。
PS:由于四周的园弧相遇时存在舍入误差,导致出现细白线。这些可以修复,但我没有去管它们。