2017-11-10 27 views
-1

그래서 한 형상 모핑에 사용되는이 클래스 :만들기 SVG 경로

class ShapeOverlays { 
    constructor(elm) { 
    this.elm = elm; 
    this.path = elm.querySelectorAll('path'); 
    this.numPoints = 18; 
    this.duration = 600; 
    this.delayPointsArray = []; 
    this.delayPointsMax = 300; 
    this.delayPerPath = 100; 
    this.timeStart = Date.now(); 
    this.isOpened = false; 
    this.isAnimating = false; 
    } 
    toggle() { 
    this.isAnimating = true; 
    const range = 4 * Math.random() + 6; 
    for (var i = 0; i < this.numPoints; i++) { 
     const radian = i/(this.numPoints - 1) * Math.PI; 
     this.delayPointsArray[i] = (Math.sin(-radian) + Math.sin(-radian * range) + 2)/4 * this.delayPointsMax; 
    } 
    if (this.isOpened === false) { 
     this.open(); 
    } else { 
     this.close(); 
    } 
    } 
    open() { 
    this.isOpened = true; 
    this.elm.classList.add('is-opened'); 
    this.timeStart = Date.now(); 
    this.renderLoop(); 
    } 
    close() { 
    this.isOpened = false; 
    this.elm.classList.remove('is-opened'); 
    this.timeStart = Date.now(); 
    this.renderLoop(); 
    } 
    updatePath(time) { 
    const points = []; 
    for (var i = 0; i < this.numPoints + 1; i++) { 
     points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0)/this.duration, 1)) * 100 
    } 

    let str = ''; 
    str += (this.isOpened) ? `M 0 0 V ${points[0]} ` : `M 0 ${points[0]} `; 
    for (var i = 0; i < this.numPoints - 1; i++) { 
     const p = (i + 1)/(this.numPoints - 1) * 100; 
     const cp = p - (1/(this.numPoints - 1) * 100)/2; 
     str += `C ${cp} ${points[i]} ${cp} ${points[i + 1]} ${p} ${points[i + 1]} `; 
    } 
    str += (this.isOpened) ? `V 0 H 0` : `V 100 H 0`; 
    return str; 
    } 
    render() { 
    if (this.isOpened) { 
     for (var i = 0; i < this.path.length; i++) { 
     this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * i))); 
     } 
    } else { 
     for (var i = 0; i < this.path.length; i++) { 
     this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * (this.path.length - i - 1)))); 
     } 
    } 
    } 
    renderLoop() { 
    this.render(); 
    if (Date.now() - this.timeStart < this.duration + this.delayPerPath * (this.path.length - 1) + this.delayPointsMax) { 
     requestAnimationFrame(() => { 
     this.renderLoop(); 
     }); 
    } 
    else { 
     this.isAnimating = false; 
    } 
    } 
} 

(function() { 
    const elmHamburger = document.querySelector('.hamburger'); 
    const gNavItems = document.querySelectorAll('.global-menu__item'); 
    const elmOverlay = document.querySelector('.shape-overlays'); 
    const overlay = new ShapeOverlays(elmOverlay); 

    elmHamburger.addEventListener('click',() => { 
    if (overlay.isAnimating) { 
     return false; 
    } 
    overlay.toggle(); 
    if (overlay.isOpened === true) { 
     elmHamburger.classList.add('is-opened-navi'); 
     for (var i = 0; i < gNavItems.length; i++) { 
     gNavItems[i].classList.add('is-opened'); 
     } 
    } else { 
     elmHamburger.classList.remove('is-opened-navi'); 
     for (var i = 0; i < gNavItems.length; i++) { 
     gNavItems[i].classList.remove('is-opened'); 
     } 
    } 
    }); 
}()); 

어떤 일이 코드를 설명해 주시겠습니까? 나는 경로가 시간을 사용하여 어떻게 생성되는지, 포인트가 어떻게 배치되는지 그리고 어떻게 수정할 수 있는지를 알지 못한다. 범위는 무엇을 위해 사용 되는가? delayPointsArray에 삼각 함수가 사용되는 이유는 무엇입니까? 왜 시간이

updatePath(time) { 
     const points = []; 
     for (var i = 0; i < this.numPoints + 1; i++) { 
      points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0)/this.duration, 1)) * 100 
     } 

     let str = ''; 
     str += (this.isOpened) ? `M 0 0 V ${points[0]} ` : `M 0 ${points[0]} `; 
     for (var i = 0; i < this.numPoints - 1; i++) { 
      const p = (i + 1)/(this.numPoints - 1) * 100; 
      const cp = p - (1/(this.numPoints - 1) * 100)/2; 
      str += `C ${cp} ${points[i]} ${cp} ${points[i + 1]} ${p} ${points[i + 1]} `; 
     } 
     str += (this.isOpened) ? `V 0 H 0` : `V 100 H 0`; 
     return str; 
     } 
     render() { 
     if (this.isOpened) { 
      for (var i = 0; i < this.path.length; i++) { 
      this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * i))); 
      } 
     } else { 
      for (var i = 0; i < this.path.length; i++) { 
      this.path[i].setAttribute('d', this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * (this.path.length - i - 1)))); 
      } 
     } 
     } 

을 사용하고 있습니다 :

기본적으로 내가하지 않습니다이 부분입니까?

this.updatePath(Date.now() - (this.timeStart + this.delayPerPath * i)) 

그래서 전달 된 time 값이 현재 시간의 차이이며, :

points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0)/this.duration, 1)) * 100 
+1

애니메이션입니다. 경과 시간에서 벗어나기를 기대하지 않습니까? –

+0

그래, 내가 그걸 이해한다는 걸 알지만, 시간이 어떻게 포인트 포지션과 일치하니. 나는이 모든 것을 처음 접했어. 조금 더 깊이 설명해 줄 수 있니? 나는 당신이이 물건에 대해 꽤 경험이 있다는 것을 알고 있습니다 ... –

+0

이 질문은'd' 프로그래밍 언어로 표기된 어떤 이유가 있습니까? – Eljay

답변

1

당신이 updatePath()가 호출되는 방식을 보면, 그것은 다음과 같이이다 : 이것의 목적은 무엇인가 우리가 작업하고있는 경로의 시작 시간.

그럼 관심있는 코드 줄은 무엇입니까?

points[i] = ease.cubicInOut(Math.min(Math.max(time - this.delayPointsArray[i], 0)/this.duration, 1)) * 100 

나는 을 무시합니다. 각도에 따라 시작 시간을 약간 수정합니다. 전체 데모를 보지 않고서도 그 이유를 알 수는 없습니다.

이 코드 라인의 목적은 현재 경로의 애니메이션이 얼마나 먼지를 계산하는 것입니다. 결과는 0에서 100까지의 좌표 값 형태로 나타납니다.

코드 한 줄에 많은 일을하고 있습니다. 개별 단계를 세분화합시다.

  1. 첫째, 우리는 다른 말로 0

    Math.max(time, 0) 
    

    최소로 경과 time 클램핑되고, 애니메이션 전에 어떤 시간이 제로가 시작한다.

  2. 그런 다음 애니메이션 기간으로 나눕니다.

    Math.max(time, 0)/duration 
    

    이렇게하면 애니메이션의 시작을 나타내는 0에서 애니메이션 끝을 나타내는 1이됩니다. 그러나 경과 시간이 애니메이션의 끝 이후 인 경우 값은 1보다 클 수 있습니다. 그러므로 다음 단계.

  3. 이제 우리는 지금이 1

    Math.min(Math.max(time, 0)/duration, 1) 
    

    최대로이 값을 고정 값> = 0, 애니메이션 과정에서 경로가 있어야한다 < = 1 whichdescribes. 애니메이션 시작 위치에 있어야한다면 0입니다. 애니메이션 끝 위치에 있어야한다면 1입니다. 그리고 애니메이션이 진행중이면 중간에 있습니다.

  4. 그러나이 값은 엄격하게 선형이며 시간의 진행에 해당합니다. 그리고 보통 선형 운동은 당신이 원하는 것이 아닙니다.부자연 스럽습니다. 객체는 움직일 때 가속하고 멈출 때 감속합니다. 그러면 easeInOut() 기능이 수행됩니다. 곡선을 부드럽게하는 데 익숙하지 않은 경우 아래 다이어그램을 살펴보십시오.

    Ease In Out timing curve

    자료 : Google: The Basics of Easing

    그래서 우리는 0..1 (수평축)에서 선형 시간 값을 전달한다. 가속 및 감속을 고려한 수정 된 값을 반환합니다.

  5. 최종 단계는 최종 좌표 값 (0..100)로 변환하는 (100)에 의해 승산한다.

희망이 있습니다.

+0

sooo 많은 감사합니다 !!!! –