requestAnimationFrame()으로 애니메이션 접기

25371 단어 cssjavascripthtml
안녕하세요, 이 기사에서는 requestAnimationFrame을 사용하여 접기 애니메이션을 수행하는 방법을 보여 드리겠습니다.

requestAnimationFrame()이란 무엇입니까?



이것은 창 방법이며 애니메이션을 수행할 것임을 브라우저에 알려줍니다.

window.requestAnimationFrame(callback);

콜백 함수가 필요하며 이 콜백은 애니메이션을 업데이트할 시간이고 브라우저에 다시 그리기를 수행할 충분한 리소스가 있을 때 실행됩니다.
  • requestAnimationFrame은 성능 및 배터리 시간 작업을 개선하기 위해 백그라운드 브라우저 탭에서 작동을 중지합니다.
  • requestAnimationFrame(callback)은 ID를 반환하고 이 ID는 콜백을 저장하며 애니메이션 취소에 사용할 수 있습니다.

  •  let animationId;
    
     animationId = requestAnimationFrame(callback);
     cancelAnimationFrame(animationId);
    

    코딩하자



    html, css 및 js 파일로 프로젝트를 만듭니다.

    HTML 파일



    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <link rel="stylesheet" href="./style.css">
    </head>
    <body>
        <button type="button" class="btn-collapse"><i class="icon"> 
          &#9650;</i>
        </button>
        <div class="collapse">
          Lorem Ipsum is simply dummy text of the printing and typesetting industry.
          Lorem Ipsum has been the industry's standard dummy text ever since the
          1500s, when an unknown printer took a galley of type and scrambled it to
          make a type specimen book. It has survived not only five centuries, but
          also the leap into electronic typesetting, remaining essentially
          unchanged. It was popularised in the 1960s with the release of Letraset
          sheets containing Lorem Ipsum passages, and more recently with desktop
          publishing software like Aldus PageMaker including versions of Lorem
          Ipsum.
        </div>
        <p>
          next line
        </p>
        <script src="./animation.js"></script>
    </body>
    </html>
    

    JS 설명



    기간 값을 저장하기 위한 상수를 만듭니다.

    const duration = 200;
    

    구성 요소 상태의 플래그를 만듭니다. 이 플래그는 구성 요소가 "축소"/"확장"되었는지 보여줍니다.

    let isCollapsed = true;
    

    요소 선택을 위한 변수를 생성합니다.

    const el = document.querySelector(".collapse");
    

    버튼과 버튼의 텍스트에 대한 변수를 만듭니다.

    const btn = document.querySelector(".btn-collapse");
    const btnTextEl = document.createElement('span');
    

    그런 다음 버튼 텍스트를 전환하는 기능을 만듭니다. 이 함수는 접힌 상태에 따라 "collapsed"/"expanded"문자열을 반환합니다.

    const getBtnText = () => (collapsed ? "collapsed" : "expanded");
    

    버튼에 텍스트와 클래스 이름을 설정합니다.

    btnTextEl.innerHTML = getBtnText(isCollapsed);
    btn.appendChild(btnTextEl);
    toggleClass(btn, "collapsed", isCollapsed);
    

    버튼 요소의 클래스 이름을 토글하는 함수를 만듭니다.

    function toggleClass(element, className, с) {
      if (с) {
        element.classList.add(className);
      } else {
        element.classList.remove(className);
      }
    }
    

    축소된 값을 토글하는 함수를 만듭니다.

    function toggleCollapsed(v) {
      return !v
    }
    

    slideDown 애니메이션에서 높이를 변경하기 위해 호출될 함수를 만들어 보겠습니다.

    function incrementHeight(el, progress) {
      /**
       * As arguments this function takes el (there is our 
       * collapse element) and 
       * progress (there is a count that we will get when we run 
       * slideDown animation) 
       */
    
      /**
       * We set to the height the value that will be increased 
       * from 0 to the scrollHeight of our element.
       */
    
      /**
       * We set this height to the style attribute of our element 
       * and as a result our element will be expanded.
       */
      el.style.height = `${progress * el.scrollHeight}px`;
    }
    

    SlideUp 이벤트에서 요소의 높이를 변경하기 위해 만드는 것과 동일한 함수입니다.

    function decrementHeight(el, progress) {
      /**
       * In this case we also override the height of the element 
       * but we need to hide element, 
       * so we subtract from the height value that was calculated 
       * progress * el.scrollHeight 
       *  */  
      height = el.scrollHeight - progress * el.scrollHeight;
      el.style.height = `${el.scrollHeight - progress * el.scrollHeight}px`;
      el.style.overflow = "hidden";
    }
    

    이제 요소를 아래로 슬라이딩하는 기능을 만들고 있습니다.

    function slideDown() {
      /**
       * First of all we need to save time when slideDown() was 
       * executed. 
       *
       */
      const start = performance.now();
    
      /**
       * Then we execute requestAnimationFrame with the callback 
       * function. For creating animation affect we should call 
       * this callback recursively.
       */
      requestAnimationFrame(function animate(time) {
        /**
         * Callback of requestAnimationFrame has the time 
         * argument, it is the timestamp.
         * Timestamp means the point in time when 
         * requestAnimationFrame() starts to execute callback 
         * functions.
         */
        /**
         * Create a variable for runtime. We get Runtime if 
         * we subtract start time from timestamp
         */
        const runtime = time - start;
    
        /**
         * Then we create a variable for progress in terms of 
         * duration. 
         * relativeProgress - is 0 then it is tart and 1 when it 
         * is 100% of animation result
         */
        const relativeProgress = runtime / duration;
    
        /**
         * We use Math.min() for avoiding situation when 
         * relativeProgress will be more than 1. 
         * 
         */
        const process = Math.min(relativeProgress, 1);
    
        /**
         * Then we create a statement for executing animate 
         * callback recursively by requestAnimationFrame
         *  It will be executed if process less than 1.
         */
        if (process < 1) {
          /**
           * In this statement we increment a height and 
           * calling requestAnimationFrame(animate).
           */
          incrementHeight(el, process);
          requestAnimationFrame(animate);
        }
    
        /**
         * We need to set height auto and reset overflow hidden if 
         * the process is 1. 
         * Cos it means the end of animation and if our container 
         * have a fixed height and 
         * overflow hidden we can meat an issue when the content 
         * in our element is more then height and
         * it will be cut.
         */
        if (process === 1) {
          el.style.height = "auto";
          el.style.overflow = "initial";
        }
      });
    }
    

    콘텐츠를 숨기는 기능을 만들어야 하며 이 기능을 slideUp이라고 합니다.

    function slideUp() {
      /**
       * The same as in slideDown().
       */
      const start = performance.now();
      requestAnimationFrame(function animate(time) {
        const runtime = time - start;
        const relativeProgress = runtime / duration;
        const process = Math.min(relativeProgress, 1);
        if (process < 1) {
          /**
           * In this statement we decrease the element height.
           */
          decrementHeight(el, process);
          requestAnimationFrame(animate);
        }
        /**
         * And at the end of our animation we remove style 
         * attribute with height and overflow,
         * cos we have this necessary style in css file.
         */
        if (process === 1) {
          el.style.height = "";
          el.style.overflow = "";
        }
      });
    }
    

    따라서 프로그래밍의 마지막 단계에서는 표시/숨기기 기능을 만듭니다. 이 함수에서는 접힌 값이 true/false인 경우 slideUp/slideDown을 호출합니다.

    function showHide(element, c) {
      toggleClass(element, "collapsed", c);
    
      if (c) {
        slideUp();
      } else {
        slideDown();
      }
    }
    

    그리고 toggleCollapsed, toggleClass 및 showHide 기능을 실행할 버튼에 클릭 이벤트를 추가합니다.

    btn.addEventListener("click", (e) => {
      e.preventDefault();
      isCollapsed = toggleCollapsed(isCollapsed);
      btnTextEl.innerHTML = getBtnText(isCollapsed);
    
      toggleClass(e.target, "collapsed", isCollapsed);
      showHide(e.target, isCollapsed);
    });
    

    스타일 추가



    축소 요소에 대한 CSS 스타일이 있습니다.

    .collapse {
      height: 0;
      overflow: hidden;
    }
    
    .btn-collapse {
      background: rgb(222, 222, 222);
      padding: 1rem;
      display: block;
      text-align-last: left;
      box-shadow: none;
      border: 1px solid #ccc;
      border-radius: 3px;
      cursor: pointer;
      width: 100%;
    }
    
    .btn-collapse span {
      pointer-events: none;
    }
    
    .icon {
      display: inline-block;
      transform: rotate(180deg);
      pointer-events: none;
    }
    
    .collapsed .icon {
      transform: rotate(0deg);
    }
    

    모두 함께




    Github 저장소




    GennadiyK / 축소 요청 애니메이션 프레임







    requestAnimationFrame으로 접기


    requestAnimationFrame이 포함된 Collapse 구성 요소의 구현이 있습니다.


    View on GitHub


    requestAnimationFrame()을 더 잘 이해하는 데 도움이 될 것 같습니다. 귀하의 의견을 남겼습니다.

    고맙습니다. 🚀 🚀 🚀

    좋은 웹페이지 즐겨찾기