gpt4 book ai didi

javascript - 在canvas中通过for循环创建形状

转载 作者:行者123 更新时间:2023-12-03 01:21:52 26 4
gpt4 key购买 nike

编辑:我将发布我所有的 html 和 js 代码,请原谅我的评论太多

我正在尝试通过 for 循环在 Canvas 中创建矩形(有输入用户)我想在另一个函数中访问它们来做一些事情,主要问题是如何在循环后访问形状的名称我已经尝试过了,但是当我在另一个函数中调用它们时,它给了我,

undefined "object name"

var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;




var c = document.getElementById("myCanvas");

//drawing the base off the towers
var base_twr1 = c.getContext("2d");
base_twr1.beginPath();
base_twr1.moveTo(550, 500);
base_twr1.lineTo(300, 500);
base_twr1.lineWidth = 10;
base_twr1.strokeStyle = '#ff0000';
base_twr1.closePath();
base_twr1.stroke();

var base_twr2 = c.getContext("2d");
base_twr2.beginPath();
base_twr2.moveTo(900, 500);
base_twr2.lineTo(650, 500);
base_twr2.closePath();
base_twr2.stroke();

var base_twr3 = c.getContext("2d");
base_twr3.beginPath();
base_twr3.moveTo(1250, 500);
base_twr3.lineTo(1000, 500);
base_twr3.closePath();
base_twr3.stroke();


//drawing the towers
var twr1 = c.getContext("2d");
twr1.beginPath();
twr1.moveTo(430, 300);
twr1.lineTo(430, 500);
twr1.closePath();
twr1.stroke();

var twr2 = c.getContext("2d");
twr2.beginPath();
twr2.moveTo(780, 300);
twr2.lineTo(780, 500);
twr2.closePath();
twr2.stroke();

var twr3 = c.getContext("2d");
twr3.beginPath();
twr3.moveTo(1130, 300);
twr3.lineTo(1130, 500);
twr3.closePath();
twr3.stroke();

//array to know each tower what contains
//to avoid collisions
var disks_in_twrs = [];
var twr1_holder = [];
var twr2_holder = [];
var twr3_holder = [];

//start function check the user input
//and call another function if everthing
//is fine
function btn_start() {
disks_number = document.getElementById("disk_input").value;
disks_number = parseInt(disks_number);
if (disks_number > 0) {
if (disks_number < 8)
put_disks(disks_number);
} else
alert('write number');

}

var width_disks_start = 305;
var height_disks_start = 490;

var disk_width = 220;

function put_disks(disks) {
for (i = 0; i < disks; i++) {
// var r = Math.floor((Math.random() * 256));
// var g = Math.floor((Math.random() * 256));
// var b = Math.floor((Math.random() * 256));

str1 = "disk";
width_disks_start = width_disks_start + 10;
height_disks_start = height_disks_start - 20;

disk_width = disk_width - 30;

// eval("disks_in_twrs.push(str1 + i)" );

// disks_in_twrs[i]=c.getContext("2d");
// disks_in_twrs[i].rect((Math.random)*100,(Math.random)*100,150,100);
// disks_in_twrs[i].stroke();
// alert(disks_in_twrs);

twr1_holder.push(str1 + i);

// ctx.fillStyle = 'rgb(' + r + ',' + g + ', ' + b + ')';
// alert(str1 + i);

//twr1_holder[i] = c.getContext("2d");
eval("var disk"+i+"= c.getContext('2d');");


// twr1_holder[i].rect(width_disks_start, height_disks_start, disk_width, 20);
eval("disk"+i+".rect(width_disks_start, height_disks_start, disk_width, 20);");
// twr1_holder[i].strokeStyle = "black";
eval("disk"+i+".strokeStyle = 'black';");
// twr1_holder[i].stroke();
eval("disk"+i+".stroke();");


// alert(disk1.toSource());


}

}
function hide_me(){
alert("byeeeeeeeeeeeeeeeee");
twr1.fillRect(430, 500, 250, 250);
// disk2.rect(515, 51, 6, 20);

// disk2.strokeStyle = 'red';

}
<!DOCTYPE html>
<html>
<head>
<title>tower of Hanoi</title>
<style type="text/css">
canvas{
border : 1px solid black;
}

</style>
</head>
<body>
<label>how many disk do you want ?</label>
<input type="text" id="disk_input">
<button id="start" onclick="btn_start()">start</button>
<label>note that maximum disk is 8 :P</label>
<button id="make_hidden" onclick="hide_me()" >make me hide</button>
<canvas id="myCanvas" >

</canvas>

<script src="tower.js">

</script>


</body>
</html>

最佳答案

这里发生了很多事情!我建议分别解决代码中的每个问题并逐渐建立理解,因为这是一个需要许多不同组件(DOM 操作/事件处理程序、JS Canvas 、对象/数组/循环、设计等)的应用程序。如果您对这些概念中的任何一个感到不舒服,请选择一个领域(例如 DOM 操作)并花时间研究简单、易于理解的示例,然后将您学到的知识应用到主应用程序中。

首先,几乎总是完全避免eval。 Mozilla 说 never to use it !如果您正在使用它,则可能意味着您的设计在整个过程中的某个地方出现了困惑,我认为这里就是这种情况。

对于事件处理程序和文档操作,我建议避免 onclick。在脚本中添加事件监听器可以完成这项工作;您可能会监听 Canvas 上的点击,以便稍后启用交互。

下一步:使用 Canvas 。通常,每个应用程序只需检索一次上下文,而不是在每次绘图之前检索上下文。除此之外,你的绘图代码看起来不错,只是它不是很好 DRY ,这通常是重新设计的信号。

最困难的部分是设计代码来实现你的目标,我对此并不完全清楚。您正在制作一款交互式汉诺塔应用程序,还是一款简单地为解算器算法提供动画且无需用户输入的应用程序?不管怎样,我选择使用对象构造函数来表示塔和磁盘。使用数组来保存这些对象意味着您可以通过塔和磁盘在数组中的位置来识别它们,而不是eval字符串名称。每当您想要对塔执行操作(例如绘制它们)时,您所需要做的就是循环遍历塔并在每个塔上调用 draw 。稍后,当涉及到处理用户输入或编写求解器算法时,操作这些数组以满足您的需求应该相当容易(例如,确定单击了哪个磁盘,在塔之间移动磁盘等)。

请记住,下面的示例只是一个帮助您入门的快速草图,可能不遵循最佳设计原则或满足您需求的原则。例如,我已经对大多数绘图坐标值进行了硬编码,因此它没有响应,所以留下了很多练习供读者改进。

const Disk = function(width, color) {
this.width = width;
this.color = color;
};

const Tower = function(x, disks) {
this.x = x;
this.disks = [];
this.width = 20;
};
Tower.prototype.draw = function(c, ctx) {
ctx.lineWidth = this.width;
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.moveTo(this.x, 0);
ctx.lineTo(this.x, c.height);
ctx.stroke();

this.disks.forEach((e, i) => {
ctx.fillStyle = e.color;
ctx.fillRect(
this.x - e.width / 2,
c.height - (i + 1) * this.width,
e.width, this.width
);
});
};

const draw = (c, ctx, towers) => {
ctx.clearRect(0, 0, c.width, c.height);
towers.forEach(t => t.draw(c, ctx));
};

const initialize = disks => {
const towers = [
new Tower(c.width / 5),
new Tower(c.width / 2),
new Tower(c.width - c.width / 5)
];

for (let i = disks; i > 0; i--) {
towers[0].disks.push(
new Disk(i * 30, `hsl(${Math.random() * 360}, 50%, 50%`)
);
}

return towers;
};

document.getElementById("initialize-form")
.addEventListener("submit", e => {
e.preventDefault();
towers = initialize(parseInt(e.target.elements[0].value), towers);
draw(c, ctx, towers);
});

document.getElementById("btn-hide").addEventListener("click",
e => document.getElementById("menu").style.display = "none"
);

const c = document.getElementById("hanoi");
c.width = 600;
c.height = 200;
const ctx = c.getContext("2d");
let towers;
body {
margin: 0;
}

#hanoi {
padding: 0.5em;
}

#initialize-form {
display: inline-block;
}

#menu {
padding: 0.5em;
display: inline-block;
}
<div id="menu">
<form id="initialize-form">
<label>Enter disks:</label>
<input type="number" min="1" max="8" value="6">
<button type="submit">start</button>
</form>
<button id="btn-hide">hide</button>
</div>
<canvas id="hanoi"></canvas>

关于javascript - 在canvas中通过for循环创建形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51730606/

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