使用 JavaScript 随机化一组现有图像的布局
Randomize the layout of a set of existing images with JavaScript
我有一个图像网格(棒球队和足球队),以及与之关联的名称(如标题)。
我想要做的是随机化带有名称的图像的位置,以便它们出现在网格的不同位置。
我可以获取要显示的图像和名称(名称来自 textarea
并存储在名称 array
中)就好了,但是一旦我点击 random 按钮,img.src
消失,留下空白点。
名称仍然是随机的并且工作正常。
到目前为止,这是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sports</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="container-fluid">
<h1>Sports Random</h1>
<br>
<div class="container">
<div class="row" id="parent">
</div>
<div class="row">
</div>
<textarea id="textarea"></textarea>
<div id="buttonGroup">
<button id="random">Random</button>
<button id="baseball">Baseball</button>
<button id="football">Football</button>
<button id="reset">Reset</button>
</div>
</div>
<br>
</div>
<script src="js/main.js"></script>
</body>
</html>
JavaScript:
bGroup.addEventListener("click", function images(e) {
tDisplay.innerHTML = "";
for (var i = 1; i < names.length; i++) {
var newDiv = document.createElement("div");
var newImg = document.createElement("img");
var userName = document.createElement("p");
newDiv.className = "col-sm-3 col-md-3 col-lg-2"
newDiv.appendChild(newImg);
newDiv.appendChild(userName);
userName.textContent = names[Math.random() * i | 0];
if (e.target.id === "baseball") {
newImg.src = "images\baseball\team" + i + ".jpg";
} else if (e.target.id === "football") {
newImg.src = "images\football\team" + i + ".gif";
}
tDisplay.appendChild(newDiv);
};
});
// random the images
random.addEventListener("click", function random() {
for (var i = 0; i < tDisplay.children.length; i++) {
tDisplay.appendChild(tDisplay.children[Math.random() * i | 0]);
tDisplay.getElementsByTagName("p")[Math.random() * i | 0].textContent =
names[Math.random() * i | 0];
}
});
现在我页面上的按钮在 div
组 (bGroup) 中,然后我根据单击的按钮委托事件。
当我对 "baseball" 和 "football" 图像有单独的功能时,我就开始工作了;只是想减少代码。
random 按钮包含在按钮组中,但为了组织方便,我将其分开;有点想知道这是否是好的做法?
如果可能的话,我希望任何答案都严格在 JavaScript 中。
干扰
问题的原因是您的 Random 按钮有自己的 "click"
事件侦听器,同时是 bGroup
的 child 也有一个"click"
事件侦听器。
导致空克隆的确切过程有点无关紧要,但可以通过使用 console.log()
.
检查(如果有兴趣)
当您点击随机时,您会同时触发tDisplay
和initialization/creation的内容随机化] 的 <div><img><p></p></div>
children.
你有两个选择:
- 附加到 Random.
的唯一侦听器中 "click"
事件的 stopPropagation()
- 或者在由
bGroup
上的 "click"
触发的函数中包含随机化功能。
我使用上面提到的第二个选项构建了下面代码的简化版本。
- 由于随机化代码
Math.random() * i | 0
是 used many times,我创建了一个函数来 return random 解析任何数字的结果通过它。
- JS 顶部的
const
声明用于存储 永远不会 更改并且在整个脚本中重复使用的值。
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.
- 我在合适的地方使用
let
而不是 var
,因为它不那么容易漏水。
let
allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var
keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
- 我选择使用
forEach()
instead of a for
循环遍历 names
,但保留了 for
循环来处理随机化。
各有千秋。
forEach()
调用的arrow function使用了两个参数; n
和 i
,其中 n
是每个循环中的 name
,而 i
是 name
的 index
(循环计数器)。
- 为了简洁起见,我也选择使用
querySelectorAll()
instead of getElementsByTagName()
。
- 这些更改有好处,但唯一显着的变化是将 随机 的
"click"
处理移动到 bGroup
上的点击处理程序中。 =101=]
请注意,随机化可能不会每次都更改显示(随机的性质),但继续单击,您会发现它确实有效;更长的 names
Array
(因此更多图像)可能会更明显地随机化。
const tDisplay = document.querySelector( ".container" ),
bGroup = document.querySelector( "#buttonGroup" ),
names = [ "foo", "bar", "baz", "qux" ];
function randIndex( i ) {
return ( Math.random() * i | 0 );
}
bGroup.addEventListener( "click", function( evt ) {
let trg = evt.target.id;
if ( trg !== "random" ) {
tDisplay.innerHTML = "";
names.forEach( ( n, i ) => {
let newDiv = document.createElement( "div" ),
newImg = document.createElement( "img" ),
userName = document.createElement( "p" );
//newDiv.className = "col-sm-3 col-md-3 col-lg-2";
newDiv.appendChild( newImg );
newDiv.appendChild( userName );
userName.textContent = names[ randIndex( i ) ];
if ( trg === "sports" ) {
newImg.src = "https://lorempixel.com/100/70/sports/" + i;
} else if ( trg === "cats") {
newImg.src = "https://lorempixel.com/100/70/cats/" + i;
}
tDisplay.appendChild( newDiv );
} );
} else {
for ( let i = 0; i < tDisplay.children.length; i++ ) {
tDisplay.appendChild( tDisplay.children[ randIndex( i ) ] );
tDisplay.querySelectorAll( "p" )[ randIndex( i ) ].textContent =
names[ randIndex( i ) ];
}
}
});
body {
font-family: sans-serif;
}
h1, p {
margin: .5em 0;
}
#buttonGroup {
margin-bottom: 1em;
}
.container div {
display: inline-block;
margin-right: 1em;
}
<h1>Images Random</h1>
<div id="buttonGroup">
<button id="random">Random</button>
<button id="sports">Sports</button>
<button id="cats">Cats</button>
</div>
<div class="container"></div>
我有一个图像网格(棒球队和足球队),以及与之关联的名称(如标题)。
我想要做的是随机化带有名称的图像的位置,以便它们出现在网格的不同位置。
我可以获取要显示的图像和名称(名称来自 textarea
并存储在名称 array
中)就好了,但是一旦我点击 random 按钮,img.src
消失,留下空白点。
名称仍然是随机的并且工作正常。
到目前为止,这是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sports</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="container-fluid">
<h1>Sports Random</h1>
<br>
<div class="container">
<div class="row" id="parent">
</div>
<div class="row">
</div>
<textarea id="textarea"></textarea>
<div id="buttonGroup">
<button id="random">Random</button>
<button id="baseball">Baseball</button>
<button id="football">Football</button>
<button id="reset">Reset</button>
</div>
</div>
<br>
</div>
<script src="js/main.js"></script>
</body>
</html>
JavaScript:
bGroup.addEventListener("click", function images(e) {
tDisplay.innerHTML = "";
for (var i = 1; i < names.length; i++) {
var newDiv = document.createElement("div");
var newImg = document.createElement("img");
var userName = document.createElement("p");
newDiv.className = "col-sm-3 col-md-3 col-lg-2"
newDiv.appendChild(newImg);
newDiv.appendChild(userName);
userName.textContent = names[Math.random() * i | 0];
if (e.target.id === "baseball") {
newImg.src = "images\baseball\team" + i + ".jpg";
} else if (e.target.id === "football") {
newImg.src = "images\football\team" + i + ".gif";
}
tDisplay.appendChild(newDiv);
};
});
// random the images
random.addEventListener("click", function random() {
for (var i = 0; i < tDisplay.children.length; i++) {
tDisplay.appendChild(tDisplay.children[Math.random() * i | 0]);
tDisplay.getElementsByTagName("p")[Math.random() * i | 0].textContent =
names[Math.random() * i | 0];
}
});
现在我页面上的按钮在 div
组 (bGroup) 中,然后我根据单击的按钮委托事件。
当我对 "baseball" 和 "football" 图像有单独的功能时,我就开始工作了;只是想减少代码。
random 按钮包含在按钮组中,但为了组织方便,我将其分开;有点想知道这是否是好的做法?
如果可能的话,我希望任何答案都严格在 JavaScript 中。
干扰
问题的原因是您的 Random 按钮有自己的 "click"
事件侦听器,同时是 bGroup
的 child 也有一个"click"
事件侦听器。
导致空克隆的确切过程有点无关紧要,但可以通过使用 console.log()
.
当您点击随机时,您会同时触发tDisplay
和initialization/creation的内容随机化] 的 <div><img><p></p></div>
children.
你有两个选择:
- 附加到 Random. 的唯一侦听器中
- 或者在由
bGroup
上的"click"
触发的函数中包含随机化功能。
"click"
事件的 stopPropagation()
我使用上面提到的第二个选项构建了下面代码的简化版本。
- 由于随机化代码
Math.random() * i | 0
是 used many times,我创建了一个函数来 return random 解析任何数字的结果通过它。 - JS 顶部的
const
声明用于存储 永远不会 更改并且在整个脚本中重复使用的值。The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.
- 我在合适的地方使用
let
而不是var
,因为它不那么容易漏水。let
allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike thevar
keyword, which defines a variable globally, or locally to an entire function regardless of block scope. - 我选择使用
forEach()
instead of afor
循环遍历names
,但保留了for
循环来处理随机化。
各有千秋。 forEach()
调用的arrow function使用了两个参数;n
和i
,其中n
是每个循环中的name
,而i
是name
的index
(循环计数器)。- 为了简洁起见,我也选择使用
querySelectorAll()
instead ofgetElementsByTagName()
。 - 这些更改有好处,但唯一显着的变化是将 随机 的
"click"
处理移动到bGroup
上的点击处理程序中。 =101=]
请注意,随机化可能不会每次都更改显示(随机的性质),但继续单击,您会发现它确实有效;更长的 names
Array
(因此更多图像)可能会更明显地随机化。
const tDisplay = document.querySelector( ".container" ),
bGroup = document.querySelector( "#buttonGroup" ),
names = [ "foo", "bar", "baz", "qux" ];
function randIndex( i ) {
return ( Math.random() * i | 0 );
}
bGroup.addEventListener( "click", function( evt ) {
let trg = evt.target.id;
if ( trg !== "random" ) {
tDisplay.innerHTML = "";
names.forEach( ( n, i ) => {
let newDiv = document.createElement( "div" ),
newImg = document.createElement( "img" ),
userName = document.createElement( "p" );
//newDiv.className = "col-sm-3 col-md-3 col-lg-2";
newDiv.appendChild( newImg );
newDiv.appendChild( userName );
userName.textContent = names[ randIndex( i ) ];
if ( trg === "sports" ) {
newImg.src = "https://lorempixel.com/100/70/sports/" + i;
} else if ( trg === "cats") {
newImg.src = "https://lorempixel.com/100/70/cats/" + i;
}
tDisplay.appendChild( newDiv );
} );
} else {
for ( let i = 0; i < tDisplay.children.length; i++ ) {
tDisplay.appendChild( tDisplay.children[ randIndex( i ) ] );
tDisplay.querySelectorAll( "p" )[ randIndex( i ) ].textContent =
names[ randIndex( i ) ];
}
}
});
body {
font-family: sans-serif;
}
h1, p {
margin: .5em 0;
}
#buttonGroup {
margin-bottom: 1em;
}
.container div {
display: inline-block;
margin-right: 1em;
}
<h1>Images Random</h1>
<div id="buttonGroup">
<button id="random">Random</button>
<button id="sports">Sports</button>
<button id="cats">Cats</button>
</div>
<div class="container"></div>