[TIL] 210927


📝 今日作った


  • 実習:ウサギを探して、座標を探して、007“性能を高めます”、ショッピングリストのアプリケーションを作成します

  • DOM/CSOM/レンダリングツリー/キーレンダリングパス/パフォーマンス向上/CSSバックグラウンドカラーグラデーション/ボーダーシャドウ/インデント/エクスポート/ENTERキーイベント
  • 📖 学習資料

  • ドリームエンコーディング「フロントエンド必須ブラウザ101」レッスン
  • 📚 学識


    1. WEB APIs


    1)ウサギを探す

  • を使用してIntoView練習
  • をスクロール
    <html>
      <head>
        <style>
          body {
            background-color: black;
          }
    
          button {
            display: block;
            margin: 0 auto;
            margin-bottom: 40px;
            background-color: lightcoral;
            color: white;
            border-style: none;
            border-radius: 5px;
            padding: 10px 10px;
            font-size: 20px;
            cursor: pointer;
          }
    
          .find-rabbit {
            display: inline;
            width: 20px;
            vertical-align: middle;
          }
    
          img {
            display: block;
            margin: 0 auto;
            width: 150px;
          }
        </style>
      </head>
      <body>
        <button>Find a rabbit&nbsp<img src="img/rabbit.png" class="find-rabbit" alt="토끼를 찾아라"></button>
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/rabbit.png" class = "rabbit" alt="토끼">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
          <img src="img/carrot.png" alt="당근">
    
        <script>
          const button = document.querySelector('button');
          const rabbit = document.querySelector('.rabbit');
    
          button.addEventListener('click', () => {
            rabbit.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});
          });
        </script>
      </body>
    </html>

    2. DOM, CCSOM, Render Tree, Critical rendering path


    1)メモ



    2)実習


    📌 WEB APIs練習(座標検索007)「性能向上」


    💡 元のコード
    const circle = document.querySelector('.circle');
    const horizon = document.querySelector('.horizon');
    const vertical = document.querySelector('.vertical');
    const coord = document.querySelector('.coord');
    
    document.addEventListener('mousemove', (event) => {
      const clientX = event.clientX;
      const clientY = event.clientY;
    
      circle.style.left = `${clientX}px`;
      circle.style.top = `${clientY}px`;
      horizon.style.top = `${clientY}px`;
      vertical.style.left = `${clientX}px`;
      coord.style.left = `${clientX}px`;
      coord.style.top = `${clientY}px`;
    
      coord.innerHTML = `${clientX}px, ${clientY}px`;
    });
  • left와 topその値が変化した場合、レイアウトから再作成し、ペンキ、合成段階を経なければならない.したがって、上記のコードはmousemoveイベントが発生するたびにこのステップを通過するため、効率が低下する.
  • 대신에 translateが望ましい.translateは、値が変更されると合成プロセスのみが発生するため、より効果的です.(CSS Triggers参照)

  • 実際には、性能が改善されたかどうかを개발자 도구의 성능 탭で調べることができる.(ctrl+shift+pを押しながら、「レイアウト変更領域表示」を選択すると、マウスを回すと表示されません.)1フレームのレンダリングに要する時間は16.67 msを超えないことが望ましい.
  • 💡 修正されたコード
    🔎 JavaScript
    const horizon = document.querySelector('.horizon');
    const vertical = document.querySelector('.vertical');
    const circle = document.querySelector('.circle');
    const coord = document.querySelector('.coord');
    
    const rectHalfWidth = circle.getBoundingClientRect().width / 2;
    const rectHalfHeight = circle.getBoundingClientRect().height / 2;
    
    
    document.addEventListener('mousemove', event => {
      const x = event.clientX;
      const y = event.clientY;
    
      horizon.style.transform = `translateY(${y}px)`;
      vertical.style.transform = `translateX(${x}px)`;
    
      circle.style.transform = `translate(${x - rectHalfWidth}px, ${y - rectHalfHeight}px)`;
    
      coord.style.transform = `translate(${x}px, ${y}px)`;
    
      coord.innerHTML = `${x}px, ${y}px`;
    ;});
    🔎 CSS
    body {
      background-color: black;
      margin: 0; /* 이벤트 리스너의 transform에 의해 line이 움직이는 시작점에 영향을 미치므로 브라우저 기본 margin 제거 */
    }
    
    .line {
      background-color: white;
      position: absolute;
    }
    
    .horizon {
      width: 100%;
      height: 1px;
      /* 기본 위치 설정해준 top 제거 */
    }
    
    .vertical {
      width: 1px;
      height: 100%;
      /* 기본 위치 설정해준 left 제거 */
    }
    
    .circle {
      position: absolute;
      /* 기본 위치 설정해준 left, top 제거 */
      /* transform: translate(-50%, -50%) 제거 (더 이상 적용 x) */
    }
    
    .coord {
      color: white;
      position: absolute;
      font-size: 30px;
      /* 기본 위치 설정해준 left, top 제거 */
      /* transform: translate(-50%, -50%) 제거 (더 이상 적용 x) */
      margin: 30px;
    }

    📌 ショッピングリストアプリケーションの作成

  • CSS背景色グラデーション
  • background: linear-gradient(45deg, red, blue);
  • ボーダーシャドウ
  • box-shadow: 0 0 5px 1px gray; // 가로 거리, 세로 거리, 흐림 정도, 퍼짐 정도, 색상
  • インデント/インデント
  • text-indent: 0.5em; // 들여쓰기
    text-indent: -0.5em; // 내어쓰기

  • Enterキーイベントif (event.keyCode === 13)またはif (event.key === "Enter")
  • 💡 改訂前、最初の成果物
    🔎 HTML
    <html>
      <body>
        <section>
          <header>
            <h1>Shopping List</h1>
          </header>
          <div id="container">
            <div id="container-lists"></div>
            <input id="container-input" type="container-text">
          </div>
          <footer>
            <button><i class="fas fa-plus-circle"></i></button>
          </footer>
        </section>
      </body>
    </html>
    🔎 CSS
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    html,
    body {
      width: 100%;
      font-family: "Gowun Batang", serif;
    }
    
    section {
      width: 450px;
      margin: 100px auto;
      border-radius: 20px;
      box-shadow: 0 0 10px gray;
    }
    
    header {
      background: linear-gradient(70deg, rgb(255, 215, 210), rgb(217, 255, 253));
      border-radius: 20px 20px 0 0;
      text-align: center;
      height: 60px;
      position: relative;
    }
    
    h1 {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      color: rgb(65, 65, 65);
    }
    
    #container {
      height: 500px;
    }
    
    #container-lists {
      height: 460px;
      background-color: rgb(252, 245, 239);
      padding: 10px 30px;
      overflow: auto;
    }
    
    #container-input {
      width: 100%;
      line-height: 40px;
      border-style: none;
      font-family: "Gowun Batang", serif;
      font-weight: bold;
      text-indent: 0.5em;
    }
    
    #container-input:focus {
      outline: none;
      box-shadow: 0.05em 0.05em 0.2em 0.1em rgb(201, 201, 201) inset;
    }
    
    footer {
      background: linear-gradient(70deg, rgb(255, 215, 210), rgb(217, 255, 253));
      border-radius: 0 0 20px 20px;
      text-align: center;
      height: 60px;
      position: relative;
    }
    
    button {
      border-style: none;
      background-color: transparent;
      cursor: pointer;
    }
    
    .fa-plus-circle {
      display: block;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      font-size: 40px;
      color: rgb(65, 65, 65);
      border-radius: 50%;
    }
    
    .fa-plus-circle:hover {
      opacity: 0.7;
      transition: all 300ms;
    }
    🔎 JavaScript
    const lists = document.querySelector('#container-lists');
    const input = document.querySelector('#container-input');
    const button = document.querySelector('button');
    
    
    function add (name) {
      if (input.value === '') {
        removeEventListener(name, this);
      } else {
        const set = document.createElement('div');
    
        set.style.display = 'flex';
        set.style.justifyContent = 'space-between';
        set.style.alignItems = 'center';
        set.style.margin = '15px 0';
        set.classList.add('set');
    
        set.innerHTML = `
        <p>${input.value}<p>
        <i class="far fa-trash-alt"></i>`;
    
        lists.appendChild(set);
        input.value = '';
    
        const sets = document.querySelectorAll('.set');
        const removeBtns = document.querySelectorAll('.far');
    
        for(let i = 0; i < sets.length; i++) {
          removeBtns[i].style.cursor = 'pointer';
          removeBtns[i].addEventListener('click', () => sets[i].remove());
        }
      }
    }
    
    button.addEventListener('click', add); // click 이벤트
    input.addEventListener('keyup', e => { // keyup 이벤트
      if (e.keyCode === 13) {
        add('keyup');
      } else {
        removeEventListener('keyup', this);
      }
    });