Радиальный слайдер SVG

Простой, отзывчивый слайдер с радиальным эффектом перехода на основе SVG clipPath и элементов маски.

 

ДЕМО
ИСХОДНИКИ

 

Во время просмотра Dribbble в мы наткнулись на эту интересную анимацию (dribbble.com/shots/2705517-boldybae) созданную Токито. Основная идея - показать небольшой предварительный просмотр следующего слайда, а затем масштабировать его, когда пользователь взаимодействует с ним.

Чтобы создать этот эффект, элементы отсечения и маскировки SVG звучали как идеальные союзники.

Давайте разберемся поэтапно: прежде всего, нам нужно было показать предварительный просмотр как предыдущих, так и следующих слайдов. Поэтому для каждого слайда нам понадобилось 2 пути: круглый элемент для обрезания части изображения, видимой в начале (навигационный CTA), и второго элемента окружности, который охватывает весь слайдер (полученный путем увеличения радиуса первого Элемент окружности).

Вот предварительный просмотр двух путей, созданных в Illustrator, на 2 отдельных монтажных платах, а затем экспортированных в виде файлов SVG. Вы найдете эти векторы внутри исходных файлов.

Используя элемент clipPath, вы можете определить видимую область изображения. Затем, очевидно, если вы анималируете элемент clipPath, вы анималируете видимую область изображения, к которому вы применяете клип.

Теперь сложная часть: анимируя элемент круга, с которым взаимодействует пользователь, мы покрываем весь слайдер, включая противоположный элемент round / navigation. Чтобы исправить это, мы использовали элемент маски SVG: в основном мы устанавливаем область, в которой элемент анимированного круга не будет виден, несмотря ни на что. Эта маска равна размеру элемента round / navigation, который мы не хотим покрывать.

Маски используют прозрачность. Поэтому, используя векторный графический инструмент, мы создали белый путь, который охватывает весь экран SVG, за исключением области, которую мы хотим замаскировать.

Вот краткая анимация, которую мы собрали вместе, чтобы показать вам идею скрытия + маскировки.

 

Создание структуры

Структура HTML состоит из двух неупорядоченных списков: ul.cd-radial-slider для слайдов и ul.cd-radial-slider-navigation для навигации слайдера.

Каждый элемент списка внутри ul.cd-radial-slider состоит из двух основных элементов: .svg-wrapper, содержащий svg с элементом <clipPath> (используемый для изменения области отсечения слайд-изображения) и <image> Element (атрибут url-образа клипа - это идентификатор <clipPath>) и .cd-radial-slider-content для содержимого слайдов.

Дополнительная .cd-round-mask используется для обертывания двух элементов <mask>.

<div class="cd-radial-slider-wrapper">
<ul class="cd-radial-slider" data-radius1="60" data-radius2="1364" data-centerx1="110" data-centerx2="1290">
<li class="visible">
<div class="svg-wrapper">
<svg viewBox="0 0 1400 800">
<title>Animated SVG</title>
<defs>
<clipPath id="cd-image-1">
<circle id="cd-circle-1" cx="110" cy="400" r="1364"/>
</clipPath>
</defs>

<image height='800px' width="1400px" clip-path="url(#cd-image-1)" xlink:href="img/img-1.jpg"></image>
</svg>
</div> <!-- .svg-wrapper -->

<div class="cd-slider-content">
<div class="wrapper">
<div>
<h2>Slide #1 Title</h2>
<p>Lorem ipsum dolor sit amet, consectetur.</p>
<a href="#0" class="cd-btn">Learn More</a>
</div>
</div>
</div> <!-- .cd-slider-content -->
</li>

<li class="next-slide">
<!-- ... -->
</li>

<!-- additional slides here -->

</ul> <!-- .cd-radial-slider -->

<ul class="cd-slider-navigation">
<li><a href="#0" class="next">Next</a></li>
<li><a href="#0" class="prev">Prev</a></li>
</ul> <!-- .cd-slider-navigation -->

<div class="cd-round-mask">
<svg viewBox="0 0 1400 800">
<defs>
<mask id="cd-left-mask" height='800px' width="1400px" x="0" y="0" maskUnits="userSpaceOnUse">
<path fill="white" d="M0,0v800h1400V0H0z M110,460c-33.137,0-60-26.863-60-60s26.863-60,60-60s60,26.863,60,60S143.137,460,110,460z"/>
</mask>

<mask id="cd-right-mask" height='800px' width="1400px" x="0" y="0" maskUnits="userSpaceOnUse">
<path fill="white" d="M0,0v800h1400V0H0z M1290,460c-33.137,0-60-26.863-60-60s26.863-60,60-60s60,26.863,60,60S1323.137,460,1290,460z"/>
</mask>
</defs>
</svg>
</div>
</div> <!-- .cd-radial-slider-wrapper -->

 

Добавление стиля

Структура слайдера довольно простая: все слайды имеют непрозрачность: 0, находятся в абсолютном положении и расположены один поверх другого (сверху: 0 и слева: 0). Класс .visible добавляется к выбранному слайду (в конце анимации обрезки), чтобы изменить его положение от абсолютного до относительного, в то время как класс .is-animating добавлен в слайд во время анимации обрезки, чтобы изменить его z-index , Классы .next-slide и .prev-slide вместо этого используются для предварительного просмотра как предыдущего, так и следующего слайдов.

Два дополнительных класса были использованы для анимации круглых элементов навигации: класс .scale-down, чтобы скрыть предварительный просмотр слайдов при выборе нового слайда (эффект масштабирования) и класс .move-up, используемый для создания эффекта щелчка, когда Нажимается один из слайд-превью.

.cd-radial-slider > li {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  opacity: 0;
  transition: transform .2s;
}
.cd-radial-slider > li.visible {
  position: relative;
  opacity: 1;
}
.cd-radial-slider > li.is-animating, 
.cd-radial-slider > li.prev-slide, 
.cd-radial-slider > li.next-slide {
  opacity: 1;
}
.cd-radial-slider > li.is-animating {
  z-index: 2;
}
.cd-radial-slider > li.scale-down, 
.cd-radial-slider > li.move-up {
  z-index: 3;
}
.cd-radial-slider > li.move-up {
  /* class added to the navigation round element when clicked - used to create the click effect */
  animation: cd-clicked .2s;
}
.cd-radial-slider > li.scale-down {
  /* class added to the navigation round element to create the scale down effect  */
  transform: scale(0);
}
.cd-radial-slider > li.next-slide {
  /* for the scale-down/click effect - change the transform origin so that it is the center of the navigation round element */
  transform-origin: 92.14% 50%;
}
.cd-radial-slider > li.prev-slide {
  transform-origin: 7.86% 50%;
}

 

Обработка событий

Чтобы реализовать радиальный слайдер SVG, мы создали объект radialSlider и использовали функцию bindEvents для присоединения обработчиков событий для перехода к навигации ползунка:

var radialSlider = function(element) {
	this.element = element;
	this.slider = this.element.find('.cd-radial-slider');
	this.slides = this.slider.children('li');
	//...
	this.navigation = this.element.find('.cd-radial-slider-navigation');
	//...
	this.bindEvents();
} 
 
radialSlider.prototype.bindEvents = function() {
	var self = this;
 
	//update visible slide when clicking the navigation round elements
	this.navigation.on('click', function(event){
		if( !self.animating ) {
			self.animating =  true;
			event.preventDefault();
			var direction = ( $(event.target).hasClass('next') ) ? 'next' : 'prev';
			//update radialSlider index properties
			self.updateIndexes(direction);
			//show new slide
			self.updateSlides(direction);
		}
	});
}

Чтобы анимировать область отсечения слайд-изображений, мы анимировали атрибут 'r' элемента <circle> внутри <clipPath>.
Мы добавили в .cd-radial-slider элемент data-radius1 и атрибут data-radius2, чтобы легко получить начальные и конечные значения радиуса, и центр данных x и центр данных x для центра <circle> (два разных значения Для следующего и предыдущего предварительного просмотра слайдов).
Затем мы использовали метод animate(), предоставляемый Snap.svg (snapsvg.io/docs/#Element.animate) для анимации элемента окружности.

clipPathVisible.animate({'r': radius2}, duration, customMinaAnimation, function(){
	//callback function here
});

Функция ослабления представляет собой пользовательскую функцию кубического безье; К сожалению, это то, что по умолчанию недоступно в Snap.svg, но вы можете создать собственную функцию синхронизации из своего пользовательского кубического безье (вот пост StackOverflow (stackoverflow.com/questions/25265197/how-to-convert-a-cubic-bezier-value-to-a-custom-mina-easing-snap-svg), который подробно описывает его).

Чтобы применить маску к видимому слайду, вместо этого мы изменили атрибут стиля элемента svg . Например, чтобы замаскировать слайд так, чтобы был показан следующий просмотр слайдов, мы использовали:

this.slides.eq(this.visibleIndex).find('image').attr('style', 'mask: url(#'+this.rightMask.attr('id')+')');

Где this.slides.eq(this.visibleIndex) - видимый слайд, а this.rightMask.attr('id') - это идентификатор элемента <mask>.

 

Вот и всё!


Top

🔖 Выбор по тегам ×

💌 Написать сообщение ×

Все поля обязательны для заполнения!