我想在金字塔图案的HTML画布上绘制圆形球。
喜欢这样:
小提琴,你可以告诉我算法:
https://jsfiddle.net/ofxmr17c/3/
var canvas = document.getElementById('canvas');
canvas.width = 400;
canvas.height = 400;
var ctx = canvas.getContext('2d');
var balls = [];
var ballsLength = 15;
var Ball = function() {
this.x = 0;
this.y = 0;
this.radius = 10;
};
Ball.prototype.draw = function(x, y) {
this.x = x;
this.y = y;
ctx.fillStyle = '#333';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
};
init();
function init() {
for (var i = 0; i < ballsLength; i++) {
balls.push(new Ball());
}
render();
}
function render() {
for (var i = 1; i <= ballsLength; i++) {
if (i >= 1 && i <= 5) {
balls[i].draw(i * 20 + balls[i].radius, 20 + balls[i].radius);
}
if (i >= 6 && i <= 9) {
balls[i].draw(i * 20 + balls[i].radius, 20 + balls[i].radius * 2);
}
if (i >= 10 && i <= 12) {
balls[i].draw(i * 20 + balls[i].radius, 20 + balls[i].radius * 3);
}
if (i >= 13 && i <= 14) {
balls[i].draw(i * 20 + balls[i].radius, 20 + balls[i].radius * 4);
}
if (i == 15) {
balls[i].draw(i * 20 + balls[i].radius, 20 + balls[i].radius * 5);
}
}
window.requestAnimationFrame(render);
}
canvas {
border: 1px solid #333;
}
<canvas id="canvas"></canvas>
我的Ball
课程包括x
,y
和radius
个变种:
var Ball = function() {
this.x = 0;
this.y = 0;
this.radius = 10;
};
然后我有Ball
类的方法在画布上绘制球:
Ball.prototype.draw = function(x, y) {
this.x = x;
this.y = y;
ctx.fillStyle = '#333';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
};
我想创建将任意数量的球放入金字塔的方法。
答案 0 :(得分:4)
下面的现场演示展示了如何使用一点三角法将任意数量的球包装到金字塔中。要更改金字塔中的图层数量(以及球的数量),请修改<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<form>
<input type="date" name="date1" required />
<input type="date" name="date2" required />
<input type="submit" />
</form>
变量。
这就是它完成时的样子:
现场演示:
NUM_ROWS
var canvas = document.getElementById('canvas');
canvas.width = 400;
canvas.height = 400;
var ctx = canvas.getContext('2d');
var balls = [];
var ballsLength = 15;
var Ball = function() {
this.x = 0;
this.y = 0;
this.radius = 10;
};
Ball.prototype.draw = function(x, y) {
this.x = x;
this.y = y;
ctx.fillStyle = '#333';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath();
};
init();
function init() {
for (var i = 0; i < ballsLength; i++) {
balls.push(new Ball());
}
render();
}
function render() {
var NUM_ROWS = 5;
for (var i = 1; i <= NUM_ROWS; i++) {
for (var j = 0; j < i; j++) {
balls[i].draw(j * balls[0].radius * 2 + 150 - i * balls[0].radius, -(i * balls[0].radius * 2 * Math.sin(Math.PI / 3)) + 150);
}
}
//window.requestAnimationFrame(render);
}
canvas {
border: 1px solid #333;
}
JSFiddle版本:https://jsfiddle.net/ofxmr17c/6/
答案 1 :(得分:1)
所以我们可以制作一个矢量(台球游戏中的其他所有东西都非常涉及矢量,所以为什么不呢!:))对于下一行起点的方向如此:
var deg60 = -60 / 180 * Math.PI; // -60°, up-right direction
var v = {
x: radius * Math.cos(deg60),
y: radius * Math.sin(deg60)
}
然后算法将(由总球数驱动):
结果:
var ctx = c.getContext("2d"),
radius = 9, // ball radius
deg = -60 / 180 * Math.PI, // direction of row start -60°
balls = 15, // number of balls to draw
drawn = 0, // count balls drawn on current row
rowLen = 1, // max length of current row (first=1)
x = 150, // start point
y = 140,
cx = 150, cy =140, // replicates start point + offsets
v = { // vector
x: radius * 2 * Math.cos(deg),
y: radius * 2 * Math.sin(deg)
},
i;
for(i = 0; i < balls; i++) {
drawBall(cx, cy); // draw ball
cx -= radius * 2; // move diameter of ball to left (in this case)
drawn++; // increase balls on row count
if (drawn === rowLen) { // reached max balls for row?
cx = x + v.x * rowLen; // increase one row
cy = y + v.y * rowLen;
drawn = 0; // reset ball count for row
rowLen++; // increase row limit
}
}
ctx.fillStyle = "#D70000";
ctx.fill();
function drawBall(x, y) {
ctx.moveTo(x + radius, y); ctx.arc(x, y, radius, 0, 6.28);
ctx.closePath();
}
<canvas id=c height=300></canvas>
如果你想在旋转方面有更多的灵活性,你可以简单地交换这一行:
cx -= radius * 2;
向量垂直(计算未显示)到第一个向量,所以:
cx += pv.x;
cy += pv.y;