Pure CSS Индикатор загрузки соответствует размеру контейнера - PullRequest
4 голосов
/ 25 января 2020

Я хочу использовать следующий индикатор загрузки для контейнеров во время загрузки данных. Проблема в том, что слайдер имеет фиксированную ширину и высоту (300 пикселей и 300 пикселей), но я хочу, чтобы он динамически помещался в контейнер. Когда я пытаюсь добавить ширину: 140px; и высота: 140 пикселей; для класса основного контейнера индикатор загрузки выглядит ужасно, а пропорции неверны.

РЕДАКТИРОВАТЬ Рикардом
Я добавил ползунок и рамку, чтобы было легче видеть, что происходит не так .

let sliderElement = document.getElementById("slider");
let mainContainerDiv = document.querySelector(".main-container");

sliderElement.oninput = function() {
  changeContainerSize(this.value);
}

function changeContainerSize(value) {
  mainContainerDiv.style.width = value + "px";
  mainContainerDiv.style.height = value + "px";
}

changeContainerSize(sliderElement.value);
.main-container {
  border: 1px solid; /* for demo purpose :: Rickard */
}
.reverse-spinner {
  position: relative;
  height: 100px;
  width: 100px;
  border: 4px solid transparent;
  border-top-color: #1976d2;
  border-left-color: #1976d2;
  border-radius: 50%;
  -webkit-animation: spin 1.5s linear infinite;
  animation: spin 1.5s linear infinite;
}
.reverse-spinner::before {
  position: absolute;
  top: 15px;
  left: 15px;
  right: 15px;
  bottom: 15px;
  content: "";
  border: 4px solid transparent;
  border-top-color: #03a9f4;
  border-left-color: #03a9f4;
  border-radius: 50%;
  -webkit-animation: spinBack 1s linear infinite;
  animation: spinBack 1s linear infinite;
}

.flexbox {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
}

.flexbox > div {
  width: 140px;
  height: 140px;
  -webkit-box-flex: 0;
  -ms-flex: 0 0 25%;
  flex: 0 0 25%;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border: 2px dashed green; /* for demo purpose :: Rickard */
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  margin: 0;
  position: relative;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  overflow: hidden;
}

-webkit-@keyframes spin {
  -webkit-from {
    -webkit-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  -webkit-to {
    -webkit-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

@-webkit-keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

@keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

@-webkit-keyframes spinBack {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(-720deg);
    transform: rotate(-720deg);
  }
}

@keyframes spinBack {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(-720deg);
    transform: rotate(-720deg);
  }
}
<input id="slider" type="range" min="100" max="500" value="500">

<div class="main-container">
  <div class="flexbox">
    <div>
      <div class="reverse-spinner"></div>
    </div>
  </div>
</div>

Ответы [ 2 ]

5 голосов
/ 25 января 2020

Вы можете изменить код счетчика, как показано ниже, чтобы полагаться на процентные значения и трюк с отступами, чтобы сохранить соотношение, тогда вы можете легко отрегулировать размер, изменяя только ширину:

.reverse-spinner {
  width: 100px;
  border: 4px solid transparent;
  border-top-color: #1976d2;
  border-left-color: #1976d2;
  border-radius: 50%;
  animation: spin 1.5s linear infinite;
}

.reverse-spinner::before {
  content: "";
  display:block;
  padding-top:calc(70% - 8px);
  margin:15%;
  border: inherit;
  border-top-color: #03a9f4;
  border-left-color: #03a9f4;
  border-radius: inherit;
  animation: spin 0.5s linear infinite reverse;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
<div class="reverse-spinner"></div>


<div class="reverse-spinner" style="width:80px;"></div>

<div class="reverse-spinner" style="width:40px;"></div>

<div class="reverse-spinner" style="width:40%;"></div>

Другая версия с меньшим количеством кода и без использования calc()

.reverse-spinner {
  width: 100px;
  background:
    radial-gradient(farthest-side at bottom,transparent 95%,#1976d2 96%) 
    top/100% 50% no-repeat;
  border-radius: 50%;
  overflow:hidden;
  animation: spin 1.5s linear infinite;
}

.reverse-spinner::before {
  content: "";
  display:block;
  padding-top:70%;
  margin:15%;
  background:
      radial-gradient(farthest-side at bottom,transparent 93%,#03a9f4 94%) 
      top/100% 50% no-repeat;
  border-radius: inherit;
  animation: spin 0.5s linear infinite reverse;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
<div class="reverse-spinner"></div>


<div class="reverse-spinner" style="width:80px;"></div>

<div class="reverse-spinner" style="width:40px;"></div>

<div class="reverse-spinner" style="width:40%;"></div>

Еще один с меньшим количеством кода:

.reverse-spinner {
  width: 100px;
  background: top/100% 50% no-repeat;
  background-image:
    radial-gradient(farthest-side at bottom,transparent 95%,#1976d2 96% 99%,transparent 100%);
  animation: spin 1.5s linear infinite;
}

.reverse-spinner::before {
  content: "";
  display:block;
  padding-top:100%;
  background:inherit;
  background-image:
    radial-gradient(farthest-side at bottom,transparent 73%,#03a9f4 74% 79%,transparent 80%);
  animation: spin 0.5s linear infinite reverse;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
<div class="reverse-spinner"></div>


<div class="reverse-spinner" style="width:80px;"></div>

<div class="reverse-spinner" style="width:50px;"></div>

<div class="reverse-spinner" style="width:40%;"></div>
4 голосов
/ 17 февраля 2020

Кроме того, вы можете сделать загрузчик с помощью SVG. В котором нужно установить viewBox =" 0 0 140 140 " Обернуть загрузчик div и установить ширину родительского контейнера в процентах.

В приведенном ниже примере используется один и тот же загрузчик id = "loader" в трех контейнерах <div class = "reverse-spinner"> с размерами: width: 10%, width: 20%, width: 30%

.reverse-spinner {
display: inline-block;
}
.container {
width:100vw;
height:100vh; 
background:#EAEAEA;
}
<div class="container" >
     <!-- Container width:10% -->
<div class="reverse-spinner" style="width:10%; background-color:gold; " >
 <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
	        viewBox="0 0 140 140"  >  
 <g id="loader" >
    <circle cx="70" cy="70" r="60" fill="none" stroke="#1976D2" stroke-width="4" stroke-dashoffset="0" stroke-dasharray="188.4" stroke-linecap="round" >
      <animate attributeName="stroke-dashoffset" begin="0s" dur="1.5s" values="0;376.8" repeatCount="indefinite" />
 </circle>   
   <circle cx="70" cy="70" r="40" fill="none" stroke="#03A9F4" stroke-width="4" stroke-dashoffset="0" stroke-dasharray="125.5" stroke-linecap="round" >
      <animate attributeName="stroke-dashoffset" begin="0s" dur="1s" values="251.2;0" repeatCount="indefinite" />
 </circle>
  </g> 
</svg>	
</div> 
         <!-- Container width:20% -->
<div class="reverse-spinner" style="width:20%; background:#31C1B0;">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
	        viewBox="0 0 140 140"  >  
     <use xlink:href="#loader" > </use> 
  </svg>	
</div>  
            <!-- Container width:30% -->
  <div class="reverse-spinner" style="width:30%; background:#FFA6E3;">
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
	        viewBox="0 0 140 140"  >  
       <use xlink:href="#loader" > </use> 
</svg>	
</div> 
</div>

В этом примере используется input для динамического изменения ширины родительского контейнера:

.container {
width: var(--w1,40px); 
background:#EAEAEA;
 
}
<div>
<input type="range" min="40" max="600" oninput="document.querySelector('.container').style.setProperty('--w1', this.value + 'px');" value="50"><span>width Container</span><br> 
</div>
<div class="container" >

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
	        viewBox="0 0 140 140" style="border:1px solid;" >  
 <g id="loader" >
<circle cx="70" cy="70" r="60" fill="none" stroke="#1976D2" stroke-width="4" stroke-dashoffset="0" stroke-dasharray="188.4" stroke-linecap="round" >
   <animate attributeName="stroke-dashoffset" begin="0s" dur="1.5s" values="0;376.8" repeatCount="indefinite" />
 </circle>   
   <circle cx="70" cy="70" r="40" fill="none" stroke="#03A9F4" stroke-width="4" stroke-dashoffset="0" stroke-dasharray="125.5" stroke-linecap="round" >
    <animate attributeName="stroke-dashoffset" begin="0s" dur="1s" values="251.2;0" repeatCount="indefinite" />
 </circle>
  </g> 
</svg>	
</div> 

ОБНОВЛЕНИЕ

Добавлен еще один пример с переносом текста вокруг родительского контейнера.

Этот пример дополнительно демонстрирует адаптируемость заполнения родительского контейнера приложением SVG.

.container {
width: var(--w1,60px); 
background:#EAEAEA;
 float:left;
 margin-right: 1em;
}
.txt {
font-size:1.2em;

}
<div class="cont" >
<input type="range" min="60" max="600" oninput="document.querySelector('.container').style.setProperty('--w1', this.value + 'px');" value="60">
</div>
<div class="container" >
<svg  viewBox="0 0 120 120">
	
<defs>
	 <mask id="msk1">
      <circle class="maskCircle" cx="60" cy="60" r="40" fill="none" stroke="white" stroke-width="8" stroke-dashoffset="0" stroke-dasharray="251.2">
	     <animate attributeName="stroke-dashoffset" dur="3s" values="251.2;0" fill="freeze" repeatCount="indefinite" />
	 </circle>
	 </mask>
</defs>
	   <circle class="background" cx="60" cy="60" r="40" fill="none" stroke="#E4E4E4" stroke-width="8" />
		<circle class="default" cx="60" cy="60" r="40" fill="none" stroke="black" stroke-width="8"
		stroke-dasharray="3.14" stroke-dashoffset="40"  mask="url(#msk1)">
		
		</circle>
</svg>
</div> 
<div class="txt">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tincidunt dignissim nibh a facilisis. Phasellus pretium nisl vel turpis suscipit, quis posuere quam laoreet. Vestibulum fringilla porttitor felis, non lacinia dolor mattis vitae. Donec gravida et purus eu pellentesque. Nam consequat nisl id velit interdum eleifend. Mauris nulla turpis, sollicitudin in vestibulum nec, ornare quis lacus. Proin eros diam, lacinia id blandit a, efficitur eget mauris. Morbi ullamcorper velit non urna malesuada molestie. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec vehicula est non nunc ultricies, sit amet pharetra nulla congue. Vestibulum hendrerit ante ac rhoncus aliquet. Quisque vitae est turpis. Nulla sit amet felis nec nisl blandit mollis.

Nullam ornare turpis quis orci hendrerit, vitae varius est tincidunt. In quis malesuada tellus. Aliquam nunc mauris, aliquam quis lectus ut, ultrices lobortis ante. Maecenas tincidunt ligula felis, in consequat lectus finibus eget. Maecenas molestie placerat odio, at malesuada risus consequat id. Integer congue facilisis enim porta pretium. Morbi scelerisque tincidunt purus, vitae rhoncus tortor tristique nec. Nullam laoreet turpis nec felis vehicula finibus.

Fusce ultricies maximus ante vitae imperdiet. Proin magna orci, pretium nec pretium id, ultricies in risus. Praesent mauris ipsum, semper nec convallis sit amet, vestibulum non enim. Quisque volutpat nulla ac nulla venenatis, ac cursus nulla laoreet. Aliquam malesuada dui a orci tristique tristique. Phasellus fringilla, velit eget ultrices efficitur, justo lacus elementum lorem, nec convallis augue lacus non dui. Aliquam erat volutpat. Mauris sagittis, sapien in tristique mollis, ex libero laoreet magna, ut pellentesque dolor augue accumsan elit. Nunc ut augue at eros sollicitudin malesuada. Pellentesque urna felis, posuere sit amet odio et, vestibulum aliquet ex. Nulla eu dolor blandit, bibendum nibh in, tincidunt ex. Ut nisl justo, tincidunt a augue et, gravida sollicitudin neque. Donec id dignissim elit, a sollicitudin leo. Aliquam placerat orci justo, et faucibus nibh volutpat vel.

Nulla varius, est eu dictum vulputate, risus tellus euismod augue, ac tempus velit elit nec dui. Duis eleifend metus eu nisi mattis scelerisque. Proin finibus neque ut pellentesque porta. Etiam quis ligula non ligula sollicitudin efficitur at a turpis. Morbi tristique maximus quam eu imperdiet. Morbi dolor augue, sagittis non urna quis, fringilla scelerisque erat. Praesent et tempor tortor. In hac habitasse platea dictumst. Sed ut consectetur arcu, id vestibulum sapien. Integer in metus et lacus sollicitudin sollicitudin. Curabitur vulputate mollis odio, sit amet dictum mauris condimentum non. Vestibulum enim risus, luctus a tristique sit amet, semper non enim. Nunc laoreet hendrerit massa at blandit.

Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris dapibus eu ipsum ac semper. Suspendisse turpis nunc, mattis sit amet lorem id, fringilla iaculis purus. Praesent egestas est id ullamcorper tristique. Nulla tempus sem rutrum, sagittis dui quis, condimentum massa. Nam efficitur purus sed sapien euismod imperdiet. Donec laoreet augue eget justo dapibus suscipit. Etiam eleifend neque iaculis, pellentesque elit vel, malesuada justo. Aenean efficitur eros quis mattis convallis. Quisque hendrerit libero ligula, vel fermentum orci ultrices vel. In porttitor congue interdum. Duis ac vehicula est. Nullam sollicitudin eros a tortor semper, laoreet facilisis neque hendrerit. Integer faucibus elementum nibh, id venenatis urna consectetur a.
</div>
...