问题描述
我想在金字塔图案的HTML画布上绘制圆形球。
像这样:
小提琴,你可以告诉我算法:
/ p>
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]。画(i * 20 +球[i] .radius,20 +球[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();
};
我想创建一个将任意数量的球放入金字塔的方法。
像这样的台球金字塔总是有一些已知的事实:
- 每一行总是包含一个比前一个更多的球
- 这是一个等边的三角形,这意味着下一行总是开始偏移60°
所以我们可以制作一个矢量(台球游戏中的其他所有内容都非常涉及矢量,所以为什么不呢! :))为下一行的起点的方向如下:
var deg60 = -60 / 180 * Math.PI ; // -60°,右上方向
var v = {
x:radius * Math.cos(deg60),
y:radius * Math.sin(deg60)
}
然后算法将(由总球数驱动):
- 从第一行的最大限制为1开始
- 绘制球直到达到行的最大限制
- 然后,添加一个到最大限额
- 重置行数
- 将位置移至开头最后一行+向量
- 重复直到达到球数
结果:
示例
var ctx = c.getContext(2d),radius = 9,//球半径deg = -60 / 180 * Math.PI,//行开始方向-60°球= 15,//绘制绘制的球数= 0,//计算当前行上绘制的球rowLen = 1,// max当前行的长度(第一个= 1)x = 150,//起始点y = 140,cx = 150,cy = 140,//复制起点+偏移量v = {//向量x:半径* 2 *数学。 cos(deg),y:radius * 2 * Math.sin(deg)},i; for(i = 0;我<球; i ++){drawBall(cx,cy); // draw ball cx - = radius * 2; //将球的直径向左移动(在这种情况下)绘制++; //如果(绘制=== rowLen){//达到行的最大球数,则增加行数? cx = x + v.x * rowLen; //增加一行cy = y + v.y * rowLen; drawn = 0; //重置行rowLen ++的球数; //增加行限制}} ctx.fillStyle =#D70000; ctx.fill();函数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;
I want to draw circular balls on an HTML canvas in a pyramid pattern.
Like this:
Fiddle where you can show me the algorithm:
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>
I have Ball
class with x
, y
and radius
variables:
var Ball = function() {
this.x = 0;
this.y = 0;
this.radius = 10;
};
Then I have method of the Ball
class which draws the balls on the canvas:
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();
};
I want to create method which will place any number of balls into a pyramid.
A billiard pyramid like this is always made with some known facts:
- Each row always contains one more ball than the previous
- It's an equilateral triangle which means next row always starts offset 60°
So we can make a vector (everything else in a billiard game would very much involve vectors so why not! :) ) for the direction of the next row's start point like so:
var deg60 = -60 / 180 * Math.PI; // -60°, up-right direction
var v = {
x: radius * Math.cos(deg60),
y: radius * Math.sin(deg60)
}
Then the algorithm would be (driven by total number of balls):
- Start with a max limit of 1 for first row
- Plot balls until max limit for row is reached
- Then, add one to the max limit
- Reset row count
- Move position to beginning of last row + vector
- Repeat until number of balls is reached
Result:
Example
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>
If you want more flexibility in terms of rotation you can simply swap this line:
cx -= radius * 2;
with a vector perpendicular (calculation not shown) to the first vector so:
cx += pv.x;
cy += pv.y;
这篇关于用金字塔图案绘制圆的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!