Как быстро развернуть SVG?

Я использую SVG в гамбургер-меню, поэтому, когда пользователь щелкает это меню, SVG расширяется и заполняет весь экран. Я использую для этого scale(), поэтому в основном SVG имеет масштаб 1, а когда пользователь нажимает на меню, SVG получает scale(35).

Теперь проблема. Это масштабирование - scale(35) не заполняет весь экран при больших разрешениях дисплея или даже на некоторых мобильных разрешениях с большей высотой. Если я установлю масштаб для чего-то, что обеспечит мне покрытие большинства экранов, например, scale(70), это сделает анимацию закрытия действительно беспорядочной при прохождении такого большого масштаба до 1.
Как я могу расширить этот SVG с помощью плавной анимации, заполняющая все типы дисплеев?

Ниже приведены некоторые изображения, объясняющие, что происходит.

Закрытое меню / SVG со 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>

Свободный перевод вопроса How to expand a SVG responsively? от участника @Pedro.


Ответы (2 шт):

Автор решения: Alexandr_TT

Вопрос в том, как быстро масштабировать blob, а не иметь только одно значение масштаба, которое может быть слишком маленьким для очень больших экранов и, наоборот, вызывать проблемы на очень маленьких дисплеях при сжатии.

Поскольку JS уже вызывается при щелчке мышью, мы можем получить базовый размер капли и посмотреть, «сколько раз» он поместится в высоту и ширину окна соответственно, и использовать эти соотношения для расчета масштаба, который гарантирует, что окно будет закрыто. но без огромного масштабирования.

Мы можем сделать это, вычислив переменную 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>

Примечание: этот фрагмент, похоже, работает с окнами разных размеров нормально, но в «эмуляторе» для мобильных устройств на Edge в Windows10 я заметил один небольшой рывок при уменьшении. Я не могу этого объяснить. Надеюсь, кто-то сможет.

Свободный перевод ответа от участника @A Haworth.

→ Ссылка
Автор решения: Alexandr_TT

Вот другой подход.

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>

Свободный перевод ответа от участника @Paul LeBeau.

→ Ссылка