4

我在汉堡菜单下使用 SVG,因此当用户单击该菜单时,SVG 会展开并用其上的选项填充整个屏幕。我为此使用了 scale(),所以基本上发生的情况是 SVG 的比例为 1,当用户单击菜单时,SVG 得到一个 scale(35)。

现在的问题。该比例(35)不会在更大的分辨率上填充整个屏幕,甚至在某些具有更大高度的移动分辨率上。如果我设置的比例可以确保我覆盖大部分屏幕,比如比例(70),这将使关闭动画非常混乱,因为将如此大的比例设置为 1。我怎样才能扩展这个 SVG一个流畅的动画,让它填满每一种类型的屏幕?

编辑 - 在下面添加了一个简单快速的示例代码

下面是一些解释发生了什么的图像。

关闭的菜单/带比例的 SVG(1) 关闭菜单/带刻度的 SVG(1)

打开的菜单/带有比例的 SVG (70) 打开的菜单/带有比例的 SVG (70)

菜单关闭 / SVG 从 scale(70) 变为 scale(1) 并且看起来很乱 菜单关闭 / SVG 从 scale(70) 变为 scale(1) 并且看起来很乱

function menuOnClick() {
  document.getElementById("menu-bar").classList.toggle("change");
  document.getElementById("nav").classList.toggle("change");
  document.getElementById('blob').classList.toggle("change-bg");
}
#menu {
  z-index: 2;
}

#menu-bar {
  width: 45px;
  height: 40px;
  margin: 30px 0 20px 20px;
  cursor: pointer;
  float: right;
}

.bar {
  height: 5px;
  width: 100%;
  background-color: #00d1a9;;
  display: block;
  border-radius: 5px;
  transition: 0.3s ease;
}

#bar1 {
  transform: translateY(-4px);
}

#bar3 {
  transform: translateY(4px);
}

.nav {
  transition: 0.3s ease;
  display: none;
}

.nav ul {
  padding: 0 22px;
}

.nav li {
  list-style: none;
  padding: 12px 0;
}

.nav li a {
  color: white;
  font-size: 20px;
  text-decoration: none;
}

.nav li a:hover {
  font-weight: bold;
}

.menu-bg, #menu {
  top: 0;
  left: 0;
  position: absolute;
}

.change {
  display: block;
}

.change .bar {
  background-color: white;
}

.change #bar1 {
  transform: translateY(4px) rotateZ(-45deg);
}

.change #bar2 {
  opacity: 0;
}

.change #bar3 {
  transform: translateY(-6px) rotateZ(45deg);
}

.change-bg {
  transform: scale(70);
}
.blob {
  margin-top:-32px;
  top: 0;
  z-index: 1;
  pointer-events: none;
  -webkit-transition: all 0.75s linear;
  transition: all 0.75s linear;
  display: block;
  will-change: auto;
    filter: none;
  -webkit-filter: blur(0);
  -moz-filter: blur(0);
  -ms-filter: blur(0);
  filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius='0');
}
<div id="menu">
  <div id="menu-bar" onclick="menuOnClick()">
    <div id="bar1" class="bar"></div>
    <div id="bar2" class="bar"></div>
    <div id="bar3" class="bar"></div>
  </div>
  <nav class="nav" id="nav">
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
      <li><a href="#">Blog</a></li>
    </ul>
  </nav> 
</div>
                                <svg class="blob" id="blob" xmlns="http://www.w3.org/2000/svg" width="265.42" height="151.973" viewBox="0 0 265.42 151.973">
                                    <title>Menu Blob</title>
                                    <desc>The blob that grows to be the menu background</desc>
                                    <path class="blobPath" id="blobPath" shape-rendering="auto" d="M-1377.154,10877.442c-10.882-7.812-24.262-11.1-36.627-16.251s-24.764-13.355-28.853-26.112c-.135.766,251.322-30.752,251.3-30.855s-9.766,33.5-15.478,42.831c-9.83,16.055-20.015,32.053-32.926,45.756a125.25,125.25,0,0,1-18.85,16.492,89.6,89.6,0,0,1-28.133,13.538,70.507,70.507,0,0,1-29.47,1.6,56.7,56.7,0,0,1-24.487-10C-1354.7,10904.193-1363.044,10887.567-1377.154,10877.442Z" transform="translate(2763.902 -10547.315) rotate(7)" />
                                </svg>

<div class="menu-bg" id="menu-bg"></div>

4

2 回答 2

3

问题是如何响应地缩放 blob,而不是只有一个缩放值,这对于非常大的屏幕来说可能太小,而在缩小时反而会在非常小的屏幕上引起问题。

由于 JS 已经在单击时被调用,我们可以获得 blob 的基本大小并查看它分别适合窗口高度和宽度的“多少次”,并使用这些比率来计算保证窗口被覆盖的比例但没有巨大的缩放。

我们可以通过在 click 事件函数中计算一个 CSS 变量来做到这一点,然后该变量将在 change-bg 类中使用(但在未设置此类时将被忽略)。这样做的好处是,如果窗口已调整大小,它将自动重新计算比例。

function menuOnClick() {
  document.getElementById("menu-bar").classList.toggle("change");
  document.getElementById("nav").classList.toggle("change");
  document.getElementById('blob').classList.toggle("change-bg");
  /* added */
  let blob = document.getElementById('blob');
  let rect = blob.getBoundingClientRect();
  document.getElementById('blob').style.setProperty('--scale', Math.max(4*window.innerWidth/rect.width,4*window.innerHeight/rect.height));
}
#menu {
  z-index: 2;
}

#menu-bar {
  width: 45px;
  height: 40px;
  margin: 30px 0 20px 20px;
  cursor: pointer;
  float: right;
}

.bar {
  height: 5px;
  width: 100%;
  background-color: #00d1a9;;
  display: block;
  border-radius: 5px;
  transition: 0.3s ease;
}

#bar1 {
  transform: translateY(-4px);
}

#bar3 {
  transform: translateY(4px);
}

.nav {
  transition: 0.3s ease;
  display: none;
}

.nav ul {
  padding: 0 22px;
}

.nav li {
  list-style: none;
  padding: 12px 0;
}

.nav li a {
  color: white;
  font-size: 20px;
  text-decoration: none;
}

.nav li a:hover {
  font-weight: bold;
}

.menu-bg, #menu {
  top: 0;
  left: 0;
  position: absolute;
}

.change {
  display: block;
}

.change .bar {
  background-color: white;
}

.change #bar1 {
  transform: translateY(4px) rotateZ(-45deg);
}

.change #bar2 {
  opacity: 0;
}

.change #bar3 {
  transform: translateY(-6px) rotateZ(45deg);
}

.blob {
  transform: scale(1); /* added */
  margin-top:-32px;
  top: 0;
  z-index: 1;
  pointer-events: none;
  -webkit-transition: all 0.75s linear;
  transition: all 0.75s linear;
  display: block;
  will-change: auto;
    filter: none;
  -webkit-filter: blur(0);
  -moz-filter: blur(0);
  -ms-filter: blur(0);
  filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius='0');
}
.change-bg { /* moved after .blob so takes precedence */
  transform: scale(var(--scale));/* Changed from 70 */
}
<div id="menu">
  <div id="menu-bar" onclick="menuOnClick()">
    <div id="bar1" class="bar"></div>
    <div id="bar2" class="bar"></div>
    <div id="bar3" class="bar"></div>
  </div>
  <nav class="nav" id="nav">
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
      <li><a href="#">Blog</a></li>
    </ul>
  </nav> 
</div>
                                <svg class="blob" id="blob" xmlns="http://www.w3.org/2000/svg" width="265.42" height="151.973" viewBox="0 0 265.42 151.973">
                                    <title>Menu Blob</title>
                                    <desc>The blob that grows to be the menu background</desc>
                                    <path class="blobPath" id="blobPath" shape-rendering="auto" d="M-1377.154,10877.442c-10.882-7.812-24.262-11.1-36.627-16.251s-24.764-13.355-28.853-26.112c-.135.766,251.322-30.752,251.3-30.855s-9.766,33.5-15.478,42.831c-9.83,16.055-20.015,32.053-32.926,45.756a125.25,125.25,0,0,1-18.85,16.492,89.6,89.6,0,0,1-28.133,13.538,70.507,70.507,0,0,1-29.47,1.6,56.7,56.7,0,0,1-24.487-10C-1354.7,10904.193-1363.044,10887.567-1377.154,10877.442Z" transform="translate(2763.902 -10547.315) rotate(7)" />
                                </svg>

<div class="menu-bg" id="menu-bg"></div>

注意:这个片段似乎可以在不同的窗口大小上工作,但在 Windows10 的 Edge 上移动设备的“模拟器”中,我注意到缩小时有一个小混蛋。我无法解释这一点。希望有人可以。

于 2021-01-08T21:49:17.967 回答
3

这是一种不同的方法。

document.getElementById("menu-bar").addEventListener('click', function(evt) {
  evt.target.parentElement.classList.toggle("open");
});
body, html {
  margin: 0;
}

#menu {
  position: relative;
}



#blob {
  position: absolute;
  top: 0;
  right: 0;
  transition: 0.3s ease;
  z-index: -1;
}

#blob g {
  fill: #00d1a9;
  transition: 0.3s ease;
  transform-origin: 150px 32px;
  transform-box: fill-box;
}

.open #blob {
  width: 100%;
  height: 100%;
}

.open #blob g {
  transform: scale(20);
}


#menu-bar {
  position: absolute;
  top: 40px;
  right: 100px;
  width: 45px;
  height: 40px;
  cursor: pointer;
}

.bar {
  height: 5px;
  width: 100%;
  background-color: rgba(255, 255, 255, 0.8);
  display: block;
  border-radius: 5px;
  transition: 0.3s ease;
  pointer-events: none;
}

#bar1 {
  transform: translateY(-4px);
}

#bar3 {
  transform: translateY(4px);
}

.open #bar1 {
  transform: translateY(4px) rotateZ(-45deg);
}

.open #bar2 {
  opacity: 0;
}

.open #bar3 {
  transform: translateY(-6px) rotateZ(45deg);
}




.nav {
  display: inline-block;
  opacity: 0;
  pointer-events: none;
}

.nav ul {
  padding: 0 22px;
  margin: 0;
}

.nav li {
  list-style: none;
  padding: 12px 0;
}

.nav li a {
  color: black;
  font-size: 20px;
  text-decoration: none;
}

.nav li a:hover {
  font-weight: bold;
}

.open .nav {
  transition: 0.3s ease;
  transition-delay: 0.2s;
  opacity: 1;
  pointer-events: auto;
}
<div id="menu">
  <svg class="blob" id="blob" width="256" height="108" viewBox="10 31 256 108">
    <g>
      <path class="blobPath" id="blobPath" shape-rendering="auto" d="M-1377.154,10877.442c-10.882-7.812-24.262-11.1-36.627-16.251s-24.764-13.355-28.853-26.112c-.135.766,251.322-30.752,251.3-30.855s-9.766,33.5-15.478,42.831c-9.83,16.055-20.015,32.053-32.926,45.756a125.25,125.25,0,0,1-18.85,16.492,89.6,89.6,0,0,1-28.133,13.538,70.507,70.507,0,0,1-29.47,1.6,56.7,56.7,0,0,1-24.487-10C-1354.7,10904.193-1363.044,10887.567-1377.154,10877.442Z" transform="translate(2763.902 -10547.315) rotate(7)" />
    </g>
  </svg>

  <div id="menu-bar">
    <div id="bar1" class="bar"></div>
    <div id="bar2" class="bar"></div>
    <div id="bar3" class="bar"></div>
  </div>

  <nav class="nav" id="nav">
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
      <li><a href="#">Blog</a></li>
    </ul>
  </nav> 
</div>

于 2021-01-09T10:16:29.263 回答