为什么此 CSS 过渡只能在某些点击时正常工作?如何解决?
Why is this CSS transition only working correctly on the some clicks? How to solve it?
我尝试用 jQuery 创建一个 CSS 转换链。第一个转换由点击事件触发,第二个由转换结束事件触发。
预期的流程是这样的:
点击 --> scale up --> wait 1s --> y 轴旋转 & shrink
要求:最后点击的元素在过渡期间必须在其他元素之前
我这样建模问题:
Class"enlarge" 用于放大,class"spinY" 用于旋转。
点击事件 --> 添加 class"enlarge"
过渡结束事件 --> 删除 class"enlarge" & class"spinY" 如果有 class"spinY" 否则添加 class"spinY"
$(function() {
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function() {
if (!$(this).hasClass("spinY", "enlarge")) {
// increment z variable & set z-index to it
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function() {
if ($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
});
});
.flat, .labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat, .flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect{
color: white;
background: #FFAA00;
}
.flat.enlarge {
-webkit-transition: all 1s ease;
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
-webkit-transition: all 1 linear 1s;
transition: all 1 linear 1s;
transform: rotateY(5turn);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
</body>
</html>
fiddle: https://jsfiddle.net/9xqvd7ng/1/
请随意尝试代码。
我希望每次点击都会触发上述相同的过程。然而,我发现除了第一次点击,其他的旋转过渡被跳过。请解释造成这种情况的原因并提供解决方案。谢谢大家!
理论上,您所做的应该可以完成工作,问题是当转换已经在进行时应用了 z-index,这只是一个同步问题。
$(function(){
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function(){
if (!$(this).hasClass("spinY", "enlarge")) {
/*
set z-index that will suffice since the other elements do not
have one defined
*/
$(this).css("z-index",1);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function(){
if($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
/*
delete the property and so clicked will always have a
greater position
*/
$(this).css("z-index","");
});
});
我 fork 了你的例子所以你可以看到它的工作
无需在JS代码中增加z-index
,只需在CSS
中将变换元素的z-index
调高即可
$(function() {
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function() {
if (!$(this).hasClass("spinY", "enlarge")) {
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function() {
if ($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
});
});
.flat,
.labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat,
.flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect {
color: white;
background: #FFAA00;
}
.flat.enlarge {
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
z-index: 1;
}
.flat.spinY {
transition: all 1 linear 1s;
transform: rotateY(5turn);
z-index: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
或者如果你想在 JS 代码中保留 z-index
,使转换更具体,这样它只针对转换,你将避免在更改 [=22= 时触发 transitionend
]:
$(function() {
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function() {
if (!$(this).hasClass("spinY", "enlarge")) {
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function() {
if ($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
});
});
.flat,
.labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat,
.flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect {
color: white;
background: #FFAA00;
}
.flat.enlarge {
transition: transform 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
transition: transform 1 linear 1s;
transform: rotateY(5turn);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
您的代码的主要问题是您正在执行 2 个属性(z-index 和变换)的转换,因此您触发了 transitionend
两次。为了更好地说明问题,请添加 console.log()
,您会注意到您正在 adding/removing 快速旋转 class:
$(function(){
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function(){
if (!$(this).hasClass("spinY", "enlarge")) {
// increment z variable & set z-index to it
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function(){
console.log('end!');
if($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
console.log('Remove class');
} else {
$(this).addClass("spinY");
console.log('add class');
}
});
});
.flat, .labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat, .flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect{
color: white;
background: #FFAA00;
}
.flat.enlarge {
-webkit-transition: all 1s ease;
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
-webkit-transition: all 1 linear 1s;
transition: all 1 linear 1s;
transform: rotateY(5turn);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
</body>
</html>
这不是第一次发生,因为最初没有为 z-index
设置值,所以您将没有过渡。
设置一个默认值,即使是第一个你也什么也得不到:
$(function(){
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function(){
if (!$(this).hasClass("spinY", "enlarge")) {
// increment z variable & set z-index to it
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function(){
console.log('end!');
if($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
console.log('Remove class');
} else {
$(this).addClass("spinY");
console.log('add class');
}
});
});
.flat, .labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat, .flat .rect {
border: 1px solid silver;
z-index:0;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect{
color: white;
background: #FFAA00;
}
.flat.enlarge {
-webkit-transition: all 1s ease;
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
-webkit-transition: all 1 linear 1s;
transition: all 1 linear 1s;
transform: rotateY(5turn);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
</body>
</html>
解决方案是要么避免更改 z-index(或任何其他 属性),要么将过渡调整为仅适用于变换。
我尝试用 jQuery 创建一个 CSS 转换链。第一个转换由点击事件触发,第二个由转换结束事件触发。
预期的流程是这样的:
点击 --> scale up --> wait 1s --> y 轴旋转 & shrink
要求:最后点击的元素在过渡期间必须在其他元素之前
我这样建模问题:
Class"enlarge" 用于放大,class"spinY" 用于旋转。
点击事件 --> 添加 class"enlarge"
过渡结束事件 --> 删除 class"enlarge" & class"spinY" 如果有 class"spinY" 否则添加 class"spinY"
$(function() {
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function() {
if (!$(this).hasClass("spinY", "enlarge")) {
// increment z variable & set z-index to it
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function() {
if ($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
});
});
.flat, .labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat, .flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect{
color: white;
background: #FFAA00;
}
.flat.enlarge {
-webkit-transition: all 1s ease;
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
-webkit-transition: all 1 linear 1s;
transition: all 1 linear 1s;
transform: rotateY(5turn);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
</body>
</html>
fiddle: https://jsfiddle.net/9xqvd7ng/1/ 请随意尝试代码。
我希望每次点击都会触发上述相同的过程。然而,我发现除了第一次点击,其他的旋转过渡被跳过。请解释造成这种情况的原因并提供解决方案。谢谢大家!
理论上,您所做的应该可以完成工作,问题是当转换已经在进行时应用了 z-index,这只是一个同步问题。
$(function(){
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function(){
if (!$(this).hasClass("spinY", "enlarge")) {
/*
set z-index that will suffice since the other elements do not
have one defined
*/
$(this).css("z-index",1);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function(){
if($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
/*
delete the property and so clicked will always have a
greater position
*/
$(this).css("z-index","");
});
});
我 fork 了你的例子所以你可以看到它的工作
无需在JS代码中增加z-index
,只需在CSS
z-index
调高即可
$(function() {
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function() {
if (!$(this).hasClass("spinY", "enlarge")) {
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function() {
if ($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
});
});
.flat,
.labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat,
.flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect {
color: white;
background: #FFAA00;
}
.flat.enlarge {
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
z-index: 1;
}
.flat.spinY {
transition: all 1 linear 1s;
transform: rotateY(5turn);
z-index: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
或者如果你想在 JS 代码中保留 z-index
,使转换更具体,这样它只针对转换,你将避免在更改 [=22= 时触发 transitionend
]:
$(function() {
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function() {
if (!$(this).hasClass("spinY", "enlarge")) {
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function() {
if ($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
} else {
$(this).addClass("spinY");
}
});
});
.flat,
.labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat,
.flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect {
color: white;
background: #FFAA00;
}
.flat.enlarge {
transition: transform 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
transition: transform 1 linear 1s;
transform: rotateY(5turn);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
您的代码的主要问题是您正在执行 2 个属性(z-index 和变换)的转换,因此您触发了 transitionend
两次。为了更好地说明问题,请添加 console.log()
,您会注意到您正在 adding/removing 快速旋转 class:
$(function(){
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function(){
if (!$(this).hasClass("spinY", "enlarge")) {
// increment z variable & set z-index to it
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function(){
console.log('end!');
if($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
console.log('Remove class');
} else {
$(this).addClass("spinY");
console.log('add class');
}
});
});
.flat, .labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat, .flat .rect {
border: 1px solid silver;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect{
color: white;
background: #FFAA00;
}
.flat.enlarge {
-webkit-transition: all 1s ease;
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
-webkit-transition: all 1 linear 1s;
transition: all 1 linear 1s;
transform: rotateY(5turn);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
</body>
</html>
这不是第一次发生,因为最初没有为 z-index
设置值,所以您将没有过渡。
设置一个默认值,即使是第一个你也什么也得不到:
$(function(){
var zValue = 0;
// event listener detect click
$(".main ").on("click", "div.flat", function(){
if (!$(this).hasClass("spinY", "enlarge")) {
// increment z variable & set z-index to it
$(this).css("z-index", ++zValue);
// add class for css transition, enlarge
$(this).addClass("enlarge");
}
});
// event listener detect end of transition
$(".main ").on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", "div.flat", function(){
console.log('end!');
if($(this).hasClass("spinY")) {
$(this).removeClass("enlarge spinY");
console.log('Remove class');
} else {
$(this).addClass("spinY");
console.log('add class');
}
});
});
.flat, .labeling {
position: relative;
background: white;
height: 3em;
width: 3em;
}
.flat, .flat .rect {
border: 1px solid silver;
z-index:0;
}
.rect {
position: relative;
left: 0.2em;
top: 0.15em;
height: 70%;
width: 80%;
text-align: center;
line-height: 200%;
}
.available .rect{
color: white;
background: #FFAA00;
}
.flat.enlarge {
-webkit-transition: all 1s ease;
transition: all 1s ease;
transform: rotateY(0turn) scale(3.2);
}
.flat.spinY {
-webkit-transition: all 1 linear 1s;
transition: all 1 linear 1s;
transform: rotateY(5turn);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div class="main">
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
<div class="flat available">
<div class="rect"></div>
</div>
</div>
</body>
</html>
解决方案是要么避免更改 z-index(或任何其他 属性),要么将过渡调整为仅适用于变换。