前言
我正在尝试创建一个具有导航菜单的响应式网站,该菜单满足以下两个要求:
- 导航在水平布局的普通浏览器窗口中完全可见
- 导航成为移动设备和小屏幕的可切换垂直菜单,在"打开"one_answers"关闭"状态之间设置动画
我希望在移动设备上表现良好,尤其是在iOS上,这意味着动画应该使用GPU加速的translate3d转换CSS转换。
我的问题
设置这个是小菜一碟,而且在大多数情况下效果很好。我使用z-index: 1
和transform: translate3d(0,-100%,0)
将菜单隐藏在标题后面,z-index: 2
处于默认关闭状态,然后使用transform: translate3d(0,0,0)
将菜单动画化为打开状态。
但我有一个问题:当我调整Chrome浏览器窗口的大小,移动媒体查询开始时,菜单会从打开状态变为关闭状态
将浏览器窗口的宽度调整到小于600像素,以查看问题的实际情况:
- 全屏jsfiddle:http://fiddle.jshell.net/ymDYG/1/show/
- 原始jsfiddle:http://jsfiddle.net/ymDYG/1/
我想我知道为什么会发生这种情况:当移动媒体查询启动时,浏览器会看到.nav
当前未处于活动状态,因此会将其设置为默认的关闭状态。我尝试过对不同的媒体查询状态使用display:none
和display:block
,但这似乎完全破坏了动画。
如何防止在调整浏览器窗口大小时启动导航菜单的"关闭"动画?
干得好,非常干净。我能偷吗?:-(
无论如何,这是您的演示解决方案。
我刚刚将过渡转移到另一个类别:
.nav {
/* stuff */
z-index: 1;
transform: translate3d(0,-100%,0);
-webkit-transform: translate3d(0,-100%,0);
}
.nav.active {
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
.nav.activated {
transition: transform 400ms linear;
-webkit-transition: -webkit-transform 400ms linear;
}
您可以在第一次"切换"时将其添加到元素中:
function toggle(){
$(".nav").addClass("activated").toggleClass("active");
}
第页。S.如果你不想在用户打开菜单并再次调整窗口大小后发生转换,你可以使用Modernizr的mq方法:
$(window).on('resize',function(){
if(Modernizr.mq('(min-width:600px)')) $(".nav").removeClass("activated");
});
提到Giona提到的副作用:
第页。S.如果你不希望转换发生,即使用户已经打开菜单,然后再次调整窗口大小(…(
有一种更干净的方法可以在不触发每个调整大小事件的情况下修复此问题。您可以在转换结束后删除可用于转换的类(此处为完整演示(:
$(function()
{
$(".nav").on("transitionend", function() {
$(this).removeClass("activated");
});
}
)();
通过结合Giona和Janusz Kacalak的回答(以及Justin Bull的评论(,我们可以进一步优化代码,使导航栏永远不会从打开状态变成关闭状态(不仅仅是第一次,这是Giona的代码所做的(。
function toggle() {
var navbar = $(".nav");
if (navbar.hasClass("active")) {
// Closing the nav bar.
navbar.removeClass("active");
// Listening for a transition.
// Use `.one` here because we only want this to be called once.
navbar.one(whichTransitionEvent(), function() {
// Remove animation property after the nav bar is closed.
navbar.removeClass("activated");
});
} else {
// Opening the nav bar.
navbar.addClass("activated").addClass("active");
}
}
// Ref: https://davidwalsh.name/css-animation-callback
function whichTransitionEvent() {
var t;
var el = document.createElement('fakeelement');
var transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
}
body { margin: 0; }
.toggle { display: none; }
.nav { list-style-type: none; margin: 0; padding: 0; }
.nav li { float: left; margin: 0; padding: 20px; background: #fdd; }
.nav li:nth-child(2n) { background: #dfd; }
@media only screen and (max-width: 599px)
{
.toggle {
display: block;
position: relative;
z-index: 2;
padding: 20px;
background: #eee;
}
.nav li {
display: block;
float: none;
}
.nav {
display: block;
position: relative;
z-index: 1;
transform: translate3d(0,-100%,0);
-webkit-transform: translate3d(0,-100%,0);
}
.nav.active {
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
.nav.activated {
transition: transform 400ms linear;
-webkit-transition: -webkit-transform 400ms linear;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#" class="toggle" onclick="javascript:toggle();return false;">Toggle menu</a>
<ul class="nav">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>