将新div的创建限制在特定区域



我有一个小页面。每隔一段时间,这里就会出现圆形的Divas。它们在随机的地方产卵。

甚至在按钮上和页面外都可以看到。

问题是,有没有可能制作一个不接触按钮的盒子,并且在这个盒子里创建圆圈?

这应该作为一个具有一定扩展的边界来完成,但以像素为单位指定所有内容不是一种选择,这对不同的屏幕来说是不好的。

我创建了这样一个框架,取代了document.body.appendChild(div);document.getElementById("spawnRadius").appendChild(div);

它们似乎应该出现在这个框架内,但不,整个页面都是一样的。

我还尝试使用所需边界的宽度和高度spawnRadius.width而不是整个页面的高度和宽度document.documentElement.clientWidth

但现在我所有的圆圈都不是随机出现的,而是在这个区块的开头一个地方。

我试图看到这些价值观​​通过console.log

console.log(documentHeight);
console.log(documentWidth);

但到达undefined

PS。全页面演示手表

//timer
var minutesLabel = document.getElementById("minutes");
var secondsLabel = document.getElementById("seconds");
var totalSeconds = 0;
setInterval(setTime, 1000);
function setTime() {
++totalSeconds;
secondsLabel.innerHTML = pad(totalSeconds % 60);
minutesLabel.innerHTML = pad(parseInt(totalSeconds / 60));
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
//create circle
var widthHeight = 65;
var margin = 25;
var delta = widthHeight + margin;
var spawnRadius = document.getElementById("spawnRadius");
let clicks = 0;
function createDiv(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = spawnRadius.height;
var documentWidth = spawnRadius.width;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.borderColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.borderColor = color; 
}
div.classList.add("circle");
div.classList.add("animation");

currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;

var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";

const nodes = document.querySelectorAll('.animation');
for(let i = 0; i < nodes.length; i++) {
nodes[i].addEventListener('click', (event) => {
event.target.style.animation = 'Animation 200ms linear';
setTimeout(() => {
event.target.style.animation = '';
}, 220);  });
}

$(div).click(function() {
$('#clicks').text(++clicks);            
$(this).fadeOut();
});

document.getElementById("spawnRadius").appendChild(div);
}

let i = 0;
const oneSecond = 600;
setInterval(() => {
i += 1;
createDiv(`circle${i}`);
}, oneSecond);
html, body {
width: 100%;
height: 100%;
margin: 0;
background: #0f0f0f;
}
.back {
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 25px;
letter-spacing: 2px;
word-spacing: 2px;
color: #ffffff;
text-shadow: 0 0 5px #ffffff, 0 0 10px #ffffff, 0 0 20px #ffffff, 0 0 40px #ff00de, 0 0 80px #ff00de, 0 0 90px #ff00de, 0 0 100px #ff00de, 0 0 150px #ff00de;
font-weight: 700;
text-decoration: none;
font-style: italic;
font-variant: normal;
text-transform: lowercase;
position: absolute;
top: 25%;
left: 2%;
user-select: none;
z-index: 999;
}
.panel {
color: #0f0f0f;
font-size: 40px;
z-index: 999;
position: absolute;
cursor: default;
user-select: none;
color: #0f0f0f;
}
.score {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.time {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.circle {
width: 60px;
height: 60px;
border-radius: 60px;
background-color: #0f0f0f;
border: 3px solid #000;
margin: 20px;
position: absolute;
}
@keyframes Animation {
0% {
transform: scale(1);
}
50% {
transform: scale(.8);
}
100% {
transform: scale(1);
}
}
#spawnRadius {
top: 55%;
height: 650px;
width: 1000px;
left: 50%;
white-space: nowrap;
position: absolute;
transform: translate(-50%, -50%);
background: #0f0f0f;
border: 2px solid #ebc6df;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="panel">
<span class="score">Score: <a id="clicks">0</a></span>
<span class="time">Time: <label id="minutes">00</label>:<label id="seconds">00</label></span>
</span>
<a href="" class="back">back</a>
<div id="spawnRadius"></div>

要回答您的主要问题,可以使用getBoundingClientRect方法来检索元素的当前边界矩形,使用该方法可以确定有效的派生区域在哪里。

选择有效位置时,只考虑容器元素的宽度和高度,因为子元素的坐标是相对于其父元素的。您还需要考虑派生的元素的大小,因此例如,x位置的有效范围是0containerWidth - circleWidth

这些圆还有一个与它们相关的CSSmargin,这将使它们偏移超过它们的绝对坐标。

不过,代码中还有一些其他问题,您稍后可能会遇到:

jQuery和标准JavaScript调用的混合很奇怪,所以如果你熟悉本地JavaScript方法,那么坚持使用这些方法并消除对jQuery的依赖可能会更简单。

例如,每个圆圈上有两个click事件处理程序,一个用于添加CSS动画,另一个用于增加分数。这些功能可以组合成一个单独的功能。

反弹动画和jQuery淡出也可以通过将opacity值添加到动画开始和结束关键帧中来组合。

createDiv函数中有一个循环,它向每个圆形元素添加了另一个点击事件处理程序,而不仅仅是向新创建的元素添加。这可能最初需要在该循环之外使用jQuery单击处理程序,因为否则分数计数器将多次递增。

在动画完成之前,也可以多次单击圆(因此添加了多个点(,这可能不是有意的。添加一个简单的布尔clicked标志可以避免这种情况。

淡入淡出动画完成后,圆形元素本身仍在页面上,它只是显示了none,因此不可见。随着时间的推移,这将导致低端硬件的速度减慢,因为内存中仍有许多不再需要的DOM元素。因此,一旦不再需要元素,最好使用removeChild从DOM中删除这些元素。您的想法是正确的,在动画完成后删除动画。

这是修改后的代码:

var minutesLabel = document.getElementById("minutes");
var secondsLabel = document.getElementById("seconds");
var clickEl = document.getElementById("clicks");
var totalSeconds = 0;
let clicks = 0;
setInterval(setTime, 1000);
function setTime() {
++totalSeconds;
secondsLabel.innerText = pad(totalSeconds % 60);
minutesLabel.innerText = pad(parseInt(totalSeconds / 60));
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}

var spawnRadius = document.getElementById("spawnRadius");
var spawnArea = spawnRadius.getBoundingClientRect();
const circleSize = 66; // Including borders
//create circle
function createDiv(id, color) {
let div = document.createElement('div');
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.borderColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.borderColor = color; 
}

// Randomly position circle within spawn area
div.style.top = `${Math.floor(Math.random() * (spawnArea.height - circleSize))}px`;
div.style.left = `${Math.floor(Math.random() * (spawnArea.width - circleSize))}px`;
div.classList.add("circle", "animation");

// Add click handler
let clicked = false;
div.addEventListener('click', (event) => {
if (clicked) { return; } // Only allow one click per circle
clicked = true;

div.style.animation = 'Animation 200ms linear forwards';
setTimeout(() => { spawnRadius.removeChild(div); }, 220);
clickEl.innerText = ++clicks
});

spawnRadius.appendChild(div);
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createDiv(`circle${i}`);
}, oneSecond);
html, body {
width: 100%;
height: 100%;
margin: 0;
background: #0f0f0f;
}
.back {
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 25px;
letter-spacing: 2px;
word-spacing: 2px;
color: #ffffff;
text-shadow: 0 0 5px #ffffff, 0 0 10px #ffffff, 0 0 20px #ffffff, 0 0 40px #ff00de, 0 0 80px #ff00de, 0 0 90px #ff00de, 0 0 100px #ff00de, 0 0 150px #ff00de;
font-weight: 700;
text-decoration: none;
font-style: italic;
font-variant: normal;
text-transform: lowercase;
position: absolute;
top: 25%;
left: 2%;
user-select: none;
z-index: 999;
}
.panel {
color: #0f0f0f;
font-size: 40px;
z-index: 999;
position: absolute;
cursor: default;
user-select: none;
color: #0f0f0f;
}
.score {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.time {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.circle {
width: 60px;
height: 60px;
border-radius: 60px;
background-color: #0f0f0f;
border: 3px solid #000;
position: absolute;
}
@keyframes Animation {
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(.8);
}
100% {
transform: scale(1);
opacity: 0;
}
}
#spawnRadius {
top: 55%;
height: 650px;
width: 1000px;
left: 50%;
white-space: nowrap;
position: absolute;
transform: translate(-50%, -50%);
background: #0f0f0f;
border: 2px solid #ebc6df;
}
<span class="panel">
<span class="score">Score: <a id="clicks">0</a></span>
<span class="time">Time: <label id="minutes">00</label>:<label id="seconds">00</label></span>
</span>
<a href="" class="back">back</a>
<div id="spawnRadius"></div>

最新更新