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

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

Сложность

radial svg slider

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

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

svg круг

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

svg анимация

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

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

svg маска

Ниже приведу пример анимации с использованием маски, для наглядности:

svg анимация маски

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

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

Каждый элемент списка внутри ul.cd-radial-slider-navigation содержит два основных элемента: контейнер .svg-wrapper содержит SVG элемент <clipPath> (обрезка области внутри слайда) и элемент <image> (чей атрибут url равен идентификатору <clipPath>), и .cs-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 -->

Добавление CSS стилей

Структура слайдера достаточно простая: все слайды имеют непрозрачность 0, расположены абсолютно друг на друге (top: 0 и left: 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 {
  animation: cd-clicked .2s;
}
.cd-radial-slider > li.scale-down {
  transform: scale(0);
}
.cd-radial-slider > li.next-slide {
  transform-origin: 92.14% 50%;
}
.cd-radial-slider > li.prev-slide {
  transform-origin: 7.86% 50%;
}

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

Для реализации радиального 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;
 
    // обновление видимого слайда при нажатии на кнопку навигации
    this.navigation.on('click', function(event){
        if( !self.animating ) {
            self.animating =  true;
            event.preventDefault();
            var direction = ( $(event.target).hasClass('next') ) ? 'next' : 'prev';
            //обновление параметров radialSlider
            self.updateIndexes(direction);
            //отображение нового слайда
            self.updateSlides(direction);
        }
    });
}

Чтобы анимировать область обрезки слайдов, мы анимируем атрибут 'r' в элементе <circle> внутри <clipPath>.
Добавляем к элементу ..cd-radial-slider и атрибут data-radius1 и data-radius2 для быстрого восстановления начального и конечного значения радиуса, а также data-centerx1 и data-centerx2 для центра элемента <circle>.
Затем используем метод animate(), предоставленный в Snap.svg для анимации круга.

clipPathVisible.animate({'r': radius2}, duration, customMinaAnimation, function(){
    //функция обратного вызова здесь
});

Чтобы применить маску к видимому слайду, мы меняем атрибут style у SVG элемента <image>. Пример отображения превью следующего слайда:

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>

ДЕМО СКАЧАТЬ Перевод статьи Radial SVG Slider

Тэги: slideranimateSVG

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.