在音程(包括小提琴)中表演后跳水的位置不正确



我的JavaScript代码有问题。我正在实现一个纸牌游戏,我点击一个按钮,13张牌应该每隔一段时间出现。

$("button").click(function() {
	let i = 0;
	setInterval(function() {
	if(i == 4) clearInterval();
	$(".block").eq(i).css({visibility:"visible"});
	$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
visibility: hidden;
}
button {
position: absolute;
top: 170px;
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<button id="button">Generate!</button>
</body>
</html>

如上所述,我使用setInterval()函数以100ms的间隔显示它们,所有div都按照我的指示执行,但它们首先出现在我想要的位置以下。我如何才能使它们直接出现在正确的位置?

提前感谢!

vertical-align: top;添加到内联元素

$("button").click(function() {
	let i = 0;
	setInterval(function() {
	if(i == 4) clearInterval();
	$(".block").eq(i).css({visibility:"visible"});
	$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
visibility: hidden;
vertical-align: top;
}
button {
position: absolute;
top: 170px;
left: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<button id="button">Generate!</button>
</body>
</html>

将块设置为display: none,然后添加display: inline-block是解决问题的一种方法,但不能解决问题本身。

主要问题是block类上的vertical-align属性集。默认情况下,此选项设置为baseline。在单击按钮之前,所有div都排成一行,不可见,其基线设置在div的底部。然而,当单击按钮时,不仅块变得可见,而且更重要的是,您在div中添加了一些文本。这会更改基线,使其成为div中文本的底部。但是,由于vertical-align: baseline,行中所有div的基线都试图对齐。有文本的可见div的基线必须与没有文本的不可见div的基准对齐。但他们的基线现在不同了,所以他们都能在基线上坐在一条直线上的唯一方法是按下带文本的div。

我简化了你的片段,让你明白我的意思。我已经使div可见,删除了按钮,而是在html中手动向div添加了一些文本。正如您所看到的,对于有文本的div,文本的底部与没有文本的div的底部对齐。

body {
background: white;
}

.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
}
<html>
<body>
<div class="block">TEXT</div>
<div class="block">TEXT</div>
<div class="block"></div>
<div class="block">TEXT</div>
</body>
</html>

一开始将块更改为display: none,然后逐个显示它们之所以有效,是因为在这种情况下,DOM中永远不会同时出现无文本的div和带文本的div,因此永远不会出现基线不匹配的情况。div进入DOM时带有文本,因此它们的基线总是匹配的。然而,这并不能完全解决问题。例如,如果div中的文本长度不同,则多行文本的底部将与单行文本的底部匹配,从而再次导致错位。

示例:

body {
background: white;
} 
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
}
<html>
<body>
<div class="block">text</div>
<div class="block">text</div>
<div class="block">very long text which takes up more than one line</div>
<div class="block">text</div>
</body>
</html>

因此,正确的解决方案是将vertical-align: top添加到block类中,以确保我们的对齐不会随着基线的变化而到处跳跃。

您可以将.block元素设置为display: none;而不是visibility: hidden;,并将脚本更改为:

$("button").click(function() {
let i = 0;
setInterval(function() {
if(i == 4) clearInterval();
$(".block").eq(i).css({display:"inline-block"});
$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});

Fiddle

您可以在.block元素周围放置一个包装器div。

<html>
<body>
<div class="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
<button id="button">Generate!</button>
</body>
</html>

然后是CSS:

.container {
display: flex;
}
.block {
/* display: inline-block; */
width: 100px;
height: 140px;
border: 2px solid;
visibility: hidden;
margin-left: 15px;
}

我为所有.block元素添加了一个左边空白,但您当然可以使用flex显示器或任何您想要的方式来设置它们。

这是一把正在工作的小提琴。

您可以将高度设置为0,然后在间隔函数中进行设置。

$("button").click(function() {
let i = 0;
setInterval(function() {
if(i == 4) clearInterval();
$(".block").eq(i).css({visibility:"visible", height: "140px"});
$(".block").eq(i).html("TEXT" + i);
i++;
},100);
});

使用此css:

.block {
display: inline-block;
width: 100px;
height: 0;
border: 2px solid;
visibility: hidden;
}
button {
position: absolute;
top: 170px;
left: 50px;
}

最新更新