Как подружить

сферу и навигацию:

меню по кривой

Всем Салют!

Меня зовут Алексей

Я веселый Front-end разработчик
Я создаю сайты, люблю

сложные анимации

творю чудеса в

преподаю в

Задача

Задача

Задача

Задача

  1. ВАУ эффект
  2. Показать технологичность компании

Зачем?

Спойлер

The SPHERE - СФЕРА 

Стартуем!

Поиск похожих решений

Все не то!

Варианты реализации

  1. CSS Transform
  2. Canvas
  3. SVG - движение по кривой
  4. Сделать видео :)

SVG - движение по кривой

Понеслась!

Сверстал меню :)

GSAP плагин - MotionPath

Размещение на кривой



let navPathSvg = "[data-sphere-path]";

navItemsLevel1.forEach((el) => {
  let tl = new gsap.timeline({paused: true});

  tl
    .to(el, {
    duration: 10,
    ease: "power1.inOut",
    motionPath: {
      path: navPath,
      align: navPath,
      alignOrigin: [0, 0.5],
      start: 0.81,
      end: 0.21
    }
  });




}
let distanse = 0.016;
let progressOffset = (1 - length * distanse) / 2;
let navPathSvg = "[data-sphere-path]";

navItemsLevel1.forEach((el) => {
  let tl = new gsap.timeline({paused: true});

  tl
    .to(el, {
    duration: 10,
    ease: "power1.inOut",
    motionPath: {
      path: navPath,
      align: navPath,
      alignOrigin: [0, 0.5],
      start: 0.81,
      end: 0.21
    }
  });
  progressOffset += distanse;

  tl.progress(progressOffset);
  tl.pause();
}

Размещение второго уровня

let progressOffset = firstLevelOffset;
//set level 2 pos
if(level2.length){
  gsap.set(level2, {autoAlpha:0});
}
level2.forEach((el)=>{
  let tl = new gsap.timeline({paused: false});

  tl
    .to(el, {
    duration: 10,
    ease: "power1.inOut",
    motionPath: {
      path: navPath,
      align: navPath,
      alignOrigin: [0, 0.5],
      start: 0.81,
      end: 0.21
    }
  });

  tl.progress(progressOffset);
  tl.pause();
});

Открытие второго уровня


////Move first level
navItemsLevel1.each(function (i) {
  let tl = $(this).data('tl');
  let offset = tl.progress() - (2 * distanse + clickedItemIndex * distanse);
  
  gsap.to(tl, {progress: offset});
});

let curTopLevelProgress = clickedItem.data('tl').progress();

//Move second level
level2.each(function (i) {
  let tl = $(this).data('tl');
  let progress = curTopLevelProgress + (i + 1) * distanse;
  gsap.fromTo(tl, {progress: curTopLevelProgress}, {progress: progress});
});

//Move first level after second
nextLevel1.each(function (i) {
  let tl = $(this).data('tl');
  let offset = tl.progress() + (level2Count) * distanse;

  gsap.to(tl, {progress: offset});
});

//Show second level
gsap.to(level2, { autoAlpha: 1, stagger: 0.05});
let distanse = 0.016;
let offset = distanse;             

let moveSphereItems = (direction) => {
  if (!isNavOpened() || isAnimated ) return;

  let isLimit = isScrollLimit();

  if (direction === 'up') {
    if(isLimit.bottom) return;
    offset *= 1;
  } else if (direction === 'down') {
    if(isLimit.top) return;

    offset *= -1;
  } else {
    return;
  }

  navItems.forEach((el) => {
    let tl = el.dataset.tl;

    let itemOffset = tl.progress() + offset;

    gsap.to(tl, {duration: 0.2, progress: itemOffset });
  }
}

Движение по скролу

Победа...

...почти

Трудности при реализации

  1. Многоуровневость - 3 уровня
  2. Линия между пунктами
  3. К-во элементов динамическое
  4. Поджимали сроки

Обсудил с дизами!

Производительность

Задача

Реализация

The SPHERE - СФЕРА 

Применение в другом проекте

this.distanse = 0.125;
////place items on arc
this.circleItems.forEach((el, index) => {

  let tl = new gsap.timeline({paused: false});

  tl
    .to(el, {
    duration: 1,
    ease: "none",
    motionPath: {
      path: this.navPath,
      align: this.navPath,
      alignOrigin: [0.5, 0.5],
      relative: true,
      start: 0,
      end: 1
    }
  });

  index =  index >= 9 ? 1 : index;
  let progressOffset = index * this.distanse;

  tl.progress(progressOffset);
  tl.pause();

});

Спасибо за внимание!

Как подружить сферу и навигацию: меню по кривой

By Alexey Kalyuzhnyi

Как подружить сферу и навигацию: меню по кривой

Поделюсь кейсом создания нестандартной навигации на сайте. Расскажу про путь от постановки задачи, через работу с дизайнерами к финальной реализации и восторгу. История включает в себя нестандартную верстку, CSS переменные, работу с SVG, GreenSock и немного боли.

  • 590