我正在编写这个函数来切换幻灯片事件,并且我试图在其上实现 Promise,但它没有达到预期的效果,只有当我使用 Promise 时我才能获得最终宽度。尽管它的工作没有承诺。
function toggleSlide(target, options){
let menu = target.children[0];
let end = options.end;
let step = options.step;
let iStep = options.iStep;
let width = start = options.start;
let isVertical = options.isVertical || false;
let removeClass, addClass, slideFn = null;
if(options.step < 0) options.step *= -1;
if(!options.hasOwnProperty('isVertical')) options.isVertical = isVertical;
if(end > start){
addClass = 'block'; // display: block; css class
removeClass = 'none'; // display: none; css class
// slideFn = slideIn;
}else{
addClass = 'none';
removeClass = 'block';
// slideFn = slideOut;
// make the menu dissapear before triggering the animation.
menu.classList.add(addClass);
menu.classList.remove(removeClass);
}
// slideFn(target, options)
// .then(() => {
// if(slideFn === slideIn){
// console.log('slideOut');
// menu.classList.add(addClass);
// menu.classList.remove(removeClass);
// }
// return;
// });
let interval = setInterval(() => {
if(width != end) width += step;
if(isVertical){
target.style.height = width + 'px';
}else{
target.style.width = width + 'px';
}
if(end < start ? width <= end : width >= end){
menu.classList.add(addClass);
menu.classList.remove(removeClass);
clearInterval(interval);
}
}, iStep);
};
这些是slideIn 和slideOut 函数:
function slideIn(element, options, arg = false){
let size = options.start || 100,
end = options.end || 0,
sStep = options.step || 1, // size step
iStep = options.iStep || 10, // interval step
isVertical = options.isVertical || false,
dirProp = isVertical ? "height" : "width",
interval = null;
if(arg){
return;
}
return new Promise(resolve => {
interval = setInterval(() => {
if(size > end) size -= sStep;
if(size <= end) size = end;
console.log(element.style[dirProp], size);
element.style[dirProp] = size + "px";
if(size === end){
clearInterval(interval);
resolve();
}
}, iStep);
});
};
function slideOut(element, options, arg = false){
let size = options.start || 0,
end = options.end || 100,
sStep = options.step || 1, // size step
iStep = options.iStep || 10, // interval step
isVertical = options.isVertical || false,
dirProp = isVertical ? "height" : "width",
interval = null;
if(arg){
return;
}
return new Promise(resolve => {
interval = setInterval(() => {
if(size < end) size += sStep;
if(size >= end) size = end;
console.log(element.style[dirProp], size);
element.style[dirProp] = size + "px";
if(size === end){
clearInterval(interval);
resolve();
}
}, iStep);
});
};
我不确定在用promise调用它时如何使元素的宽度逐渐更新,这与函数调用本身有关吗?或者使用 async/await 中的 HTMLelements 行为。我不确定问题出在哪里。
这是更正后的代码片段。
function toggle(target /*, args */ ) {
const isActive = (function(target) {
if (target.classList.contains('active')) {
target.classList.remove('active');
} else {
target.classList.add('active');
}
return target.classList.contains('active')
})(target);
const data = isActive ? {
start: 35,
end: 120,
step: 5,
iStep: 10
} : {
start: 120,
end: 35,
step: -5,
iStep: 10
};
const menu = document.getElementById('menu-links');
toggleSlide(menu, data);
};
function toggleSlide(target, options, className = null) {
let menu = target.children[0];
let end = options.end;
let step = options.step;
let iStep = options.iStep;
let size = start = options.start;
let isVertical = options.isVertical || false;
let removeClass, addClass, slideFn = null;
if (options.step < 0) options.step *= -1;
if (!options.hasOwnProperty('isVertical')) options.isVertical = isVertical;
if (end > start) {
addClass = 'block'; // display: block; css class
removeClass = 'none'; // display: none; css class
slideFn = slideOut;
} else {
addClass = 'none';
removeClass = 'block';
slideFn = slideIn;
// make the menu dissapear before triggering the animation.
menu.classList.add(addClass);
menu.classList.remove(removeClass);
}
// slideFn(target, options, true);
// if(slideFn === slideOut){
// menu.classList.add(addClass);
// menu.classList.remove(removeClass);
// }
slideFn(target, options)
.then(() => {
if (slideFn === slideOut) {
menu.classList.add(addClass);
menu.classList.remove(removeClass);
}
return;
});
// let interval = setInterval(() => {
// if(size != end) size += step;
// if(isVertical){
// target.style.height = size + 'px';
// }else{
// target.style.width = size + 'px';
// }
// // console.log(slideFn === slideOut, menu);
// if(end < start ? size <= end : size >= end){
// // if(end > start)
// // menu.classList.add(className);
// menu.classList.add(addClass);
// menu.classList.remove(removeClass);
// clearInterval(interval);
// }
// }, iStep);
};
function slideIn(element, options, arg = false) {
let size = options.start || 100,
end = options.end || 0,
sStep = options.step || 1, // size step
iStep = options.iStep || 10, // interval step
isVertical = options.isVertical || false,
dirProp = isVertical ? "height" : "width",
interval = null;
if (arg) {
console.log("slideIn with no Promise")
interval = setInterval(() => {
if (size > end) size -= sStep;
element.style[dirProp] = size + "px";
if (size <= end) {
element.style[dirProp] = end + "px";
clearInterval(interval);
}
}, iStep);
return;
}
return new Promise(resolve => {
interval = setInterval(() => {
if (size > end) size -= sStep;
element.style[dirProp] = size + "px";
if (size <= end) {
element.style[dirProp] = end + "px";
clearInterval(interval);
resolve();
}
}, iStep);
});
};
function slideOut(element, options, arg = false) {
let size = options.start || 0,
end = options.end || 100,
sStep = options.step || 1, // size step
iStep = options.iStep || 10, // interval step
isVertical = options.isVertical || false,
dirProp = isVertical ? "height" : "width",
interval = null;
if (arg) {
console.log("slideOut with no Promise")
interval = setInterval(() => {
if (size < end) size += sStep;
element.style[dirProp] = size + "px";
if (size >= end) {
element.style[dirProp] = end + "px";
clearInterval(interval);
}
}, iStep);
return;
}
return new Promise(resolve => {
interval = setInterval(() => {
if (size < end) size += sStep;
element.style[dirProp] = size + "px";
if (size >= end) {
element.style[dirProp] = end + "px";
clearInterval(interval);
resolve();
}
}, iStep);
});
};
.lb {
background-color: lightblue;
}
.none {
display: none;
}
.block {
display: block;
}
.active {
display: block;
}
.link {
padding: 10px;
margin: 5px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
#container {
width: 180px;
height: 125px;
position: relative;
}
/* #menu{} */
#menu {
position: relative;
z-index: 2;
width: 30px;
cursor: pointer;
}
#menu:before,
#menu:after,
#menu div {
background: black;
content: "";
display: block;
height: 4px;
border-radius: 3px;
margin: 3px 0;
transition: 0.2s;
}
#menu.active:before {
transform: translateY(7px) rotate(135deg);
}
#menu.active:after {
transform: translateY(-7px) rotate(-135deg);
}
#menu.active div {
transform: scale(0);
}
#menu-links {
min-width: 35px;
max-width: 120px;
padding: 2px;
padding-top: 30px;
min-height: 114px;
display: none;
position: absolute;
top: 5px;
z-index: 1;
}
#menu-links ul li {
margin: 1px 0;
}
#menu-links.active {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title Here</title>
</head>
<body>
<div id="container" class="link">
<div id="menu" onclick="toggle(this)">
<div>
</div>
</div>
<div id="menu-links" class="lb active">
<ul class="none">
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>Login</li>
</ul>
</div>
</div>
</body>
</html>