2017-11-10 5 views
-1

でSVGパスの作成:だから私は、形状モーフィングのために使用され、このクラス持ってjavascriptの(形状モーフィング)

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行のコードで大変です。だから個々のステップを分解してみましょう。

  1. まず、我々は、アニメーション開始時間の前に何かがゼロになる、すなわち0

    Math.max(time, 0) 
    

    の最小値に経過timeをクランプしています。

  2. 次に、アニメーションの継続時間で除算します。

    Math.max(time, 0)/duration 
    

    これは、アニメーションの終了を示す、1に、アニメーションの開始を示す、0から値をもたらすであろう。ただし、経過時間がアニメーションの終了後である場合、値は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. 最終ステップでは、100を掛けて最終座標値(0..100)に変換します。

希望します。

+0

ありがとうsooo so much !!!! –

関連する問題