Native Speech Recognition

목표

웹캠 촬영에 이어 음성인식을 구현해 보려함
진짜 자바스크립트는 안되는게 없나봄

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Speech Detection</title>
</head>
<body>
  <div class="words" contenteditable>
  </div>
<script>
  window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
</script>

<style>
html {
  font-size: 10px;
}
body {
  background:#ffc600;
  font-family: 'helvetica neue';
  font-weight: 200;
  font-size: 20px;
}

.words {
  max-width:500px;
  margin:50px auto;
  background:white;
  border-radius:5px;
  box-shadow:10px 10px 0 rgba(0,0,0,0.1);
  padding:1rem 2rem 1rem 5rem;
  background: -webkit-gradient(linear, 0 0, 0 100%, from(#d9eaf3), color-stop(4%, #fff)) 0 4px;
  background-size: 100% 3rem;
  position: relative;
  line-height:3rem;
}
p {
  margin: 0 0 3rem;
}

.words:before {
  content: '';
  position: absolute;
  width: 4px;
  top: 0;
  left: 30px;
  bottom: 0;
  border: 1px solid;
  border-color: transparent #efe4e4;
}
</style>
</body>
</html>

과정

코드 분석

  1. 브라우저에서 음성인식을 위해 설정

    window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    

    브라우저에 따라 webkit속성을 적용

  2. 음성인식을 할 수 있도록 상수 생성

    const recognition = new SpeechRecognition();
    recognition.interimResults = true;
    

    recognition에 음성인식을 할 수 있는 함수를 담아 반환값을 주도록 함

  3. 말한 내용을 p태그로 브라우저에 표시

    let p = document.createElement('p');
    const words = document.querySelector('.words');
    words.appendChild(p);
    
    recognition.addEventListener('result', e => {
     const transcript = Array.from(e.results)
       .map(result => result[0])
       .map(result => result.transcript)
       .join('');
    
       const poopScript = transcript.replace(/poop|poo|shit|dump/gi, '💩');
       p.textContent = poopScript;
    
       if (e.results[0].isFinal) {
         p = document.createElement('p');
         words.appendChild(p);
       }
    });
    

    words에 클래스가 word인 요소를 담아 말하는 내용을 담음
    음성인식의 결과를 배열로 변환해 텍스트에 담고, 비속어는 💩로 표시함
    말이 끝나면 p에 한 문장으로 내용을 담고 말이 끝나면 새로운 문장에 다시 시작됨

  4. 이벤트 실행

    recognition.addEventListener('end', recognition.start);
    
    recognition.start();
    

    말을 하면 음성인식이 시작되고, 멈추면 음성인식이 다시 시작된다

찾아본 내용, 알게된 내용들

webkit - 사파리에서 사용하다 브라우저 전역으로 확대, 각종 기능들을 가지고 있음


'개발 > JavaScript30' 카테고리의 다른 글

22. Following Along Link Highlight  (0) 2017.04.18
21. Geolocation  (0) 2017.04.17
20. Native Speech Recognition  (1) 2017.04.17
19. Webcam Fun  (0) 2017.04.17
18. Adding Up Times with Reduce  (0) 2017.04.16
17. Sort Without Articles  (0) 2017.04.13
  1. JW 2018.06.15 10:29

    안녕하세요:0
    자바스크립트로 STT를 구현하려고 하는데 정말 잘 봤습니다.
    제가 그대로 진행해보았는데 마이크가 차단된 페이지라고 나오네요ㅠ
    setting에서 마이크차단을 풀어도 계속 그러네요,,
    혹시 해결방법을 아시나요?ㅠ
    좋은 내용 정말 감사합니다!!

Webcam Fun

목표

페이지로 사진을 찍을 수 있게 웹캠기능을 적용

기본 코드

//HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Get User Media Code Along!</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <div class="photobooth">
    <div class="controls">
      <button onClick="takePhoto()">Take Photo</button>
<!--       <div class="rgb">
        <label for="rmin">Red Min:</label>
        <input type="range" min=0 max=255 name="rmin">
        <label for="rmax">Red Max:</label>
        <input type="range" min=0 max=255 name="rmax">

        <br>

        <label for="gmin">Green Min:</label>
        <input type="range" min=0 max=255 name="gmin">
        <label for="gmax">Green Max:</label>
        <input type="range" min=0 max=255 name="gmax">

        <br>

        <label for="bmin">Blue Min:</label>
        <input type="range" min=0 max=255 name="bmin">
        <label for="bmax">Blue Max:</label>
        <input type="range" min=0 max=255 name="bmax">
      </div> -->
    </div>

    <canvas class="photo"></canvas>
    <video class="player"></video>
    <div class="strip"></div>
  </div>

  <audio class="snap" src="http://wesbos.com/demos/photobooth/snap.mp3" hidden></audio>

  <script src="scripts-FINISHED.js"></script>

</body>
</html>

과정

  1. 요소에 대응되는 상수 생성
  2. 화면에 웹캠 출력
  3. 웹캠의 크기, 위치조정
  4. 사진을 찍고, 저장할 수 있도록 함수 생성
  5. 웹캠에 효과 설정 레인지바 생성, 실행

코드 분석

  1. 요소에 대응되는 상수 생성

    const video = document.querySelector('.player');
    const canvas = document.querySelector('.photo');
    const ctx = canvas.getContext('2d');
    const strip = document.querySelector('.strip');
    const snap = document.querySelector('.snap');
    
  2. 화면에 웹캠 출력

    function getVideo() {
    navigator.mediaDevices.getUserMedia({ video: true, audio: false })
     .then(localMediaStream => {
       console.log(localMediaStream);
       video.src = window.URL.createObjectURL(localMediaStream);
       video.play();
     })
     .catch(err => {
       console.error(`OH NO!!!`, err);
     });
    }
    

    getViedo함수에 실시간으로 웹캠의 화면이 나올수 있도록 내용을 작성해주고,
    에러가 있을때 콘솔에 ‘OH NO!!!’라는 메세지가 실행되도록 함

  3. 웹캠의 크기, 위치조정

    function paintToCanvas() {
    const width = video.videoWidth;
    const height = video.videoHeight;
    canvas.width = width;
    canvas.height = height;
    
    return setInterval(() => {
     ctx.drawImage(video, 0, 0, width, height);
     let pixels = ctx.getImageData(0, 0, width, height);
    
     ctx.putImageData(pixels, 0, 0);
    }, 16);
    }
    

    웹캠에서 효과를 적용할 범위를 웹캠의 가로, 세로길이에 맞춰 widthheight에 담고
    중앙에 효과가 적용될 새로운 웹캠 화면을 띄워줌

  4. 사진을 찍고, 저장할 수 있도록 함수 생성

    function takePhoto() {
    // played the sound
    snap.currentTime = 0;
    snap.play();
    
    // take the data out of the canvas
    const data = canvas.toDataURL('image/jpeg');
    const link = document.createElement('a');
    link.href = data;
    link.setAttribute('download', 'handsome');
    link.innerHTML = `<img src="${data}" alt="Handsome Man" />`;
    strip.insertBefore(link, strip.firsChild);
    }
    

    takePhoto()에 버튼을 눌러 사진을 찍으면 찰칵 소리가나도록 소리를 삽입하고,
    이미지를 저장할 수 있도록 파일 형식을 설정하고 다운받을수 있도록 함
    또한 찍은 이미지가 웹캠 아래에 순서대로 정렬되도록 함

  5. 웹캠에 효과 설정 레인지바 생성, 실행

    function redEffect(pixels) {
    for(let i = 0; i < pixels.data.length; i+=4) {
     pixels.data[i + 0] = pixels.data[i + 0] + 200; // RED
     pixels.data[i + 1] = pixels.data[i + 1] - 50; // GREEN
     pixels.data[i + 2] = pixels.data[i + 2] * 0.5; // Blue
    }
    return pixels;
    }
    function rgbSplit(pixels) {
    for(let i = 0; i < pixels.data.length; i+=4) {
     pixels.data[i - 150] = pixels.data[i + 0]; // RED
     pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
     pixels.data[i - 550] = pixels.data[i + 2]; // Blue
    }
    return pixels;
    }
    function greenScreen(pixels) {
    const levels = {};
    
    document.querySelectorAll('.rgb input').forEach((input) => {
     levels[input.name] = input.value;
    });
    for (i = 0; i < pixels.data.length; i = i + 4) {
     red = pixels.data[i + 0];
     green = pixels.data[i + 1];
     blue = pixels.data[i + 2];
     alpha = pixels.data[i + 3];
    
     if (red >= levels.rmin
       && green >= levels.gmin
       && blue >= levels.bmin
       && red <= levels.rmax
       && green <= levels.gmax
       && blue <= levels.bmax) {
       // take it out!
       pixels.data[i + 3] = 0;
     }
    }
    return pixels;
    }
    getVideo();
    video.addEventListener('canplay', paintToCanvas);
    

    이미지에 효과 부여 및 이벤트 실행

찾아본 내용, 알게된 내용들

길기도 길고 실용성이 너무 떨어지지만 빼먹긴 싫어서 일단 포스팅했지만, 나중에 내용 보충해야할듯..

'개발 > JavaScript30' 카테고리의 다른 글

21. Geolocation  (0) 2017.04.17
20. Native Speech Recognition  (1) 2017.04.17
19. Webcam Fun  (0) 2017.04.17
18. Adding Up Times with Reduce  (0) 2017.04.16
17. Sort Without Articles  (0) 2017.04.13
16. Mouse Move Shadow  (0) 2017.04.13

Adding Up Times with Reduce

목표

목록의 동영상들의 총 재생시간을 구하는 것

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Videos</title>
</head>
<body>
  <ul class="videos">
    <li data-time="5:43">
      Video 1
    </li>
    <li data-time="2:33">
      Video 2
    </li>
    <li data-time="3:45">
      Video 3
    </li>
    <li data-time="0:47">
      Video 4
    </li>
    <li data-time="5:21">
      Video 5
    </li>
    <li data-time="6:56">
      Video 6
    </li>
    <li data-time="3:46">
      Video 7
    </li>
    <li data-time="5:25">
      Video 8
    </li>
    <li data-time="3:14">
      Video 9
    </li>
    <li data-time="3:31">
      Video 10
    </li>
  </ul>
<script>
</script>
</body>
</html>

과정

  1. 배열 선언
  2. 동영상들의 총 재생시간을 초단위로 구함
  3. 총 재생시간을 시, 분, 초로 바꿔줌

코드 분석

  1. 배열 선언

    const timeNodes = Array.from(document.querySelectorAll('[data-time]'));
    

    timeNode[data-time]을 가진 태그들을 배열로 담아준다.

  2. 동영상들의 총 재생시간을 초단위로 구함

    const seconds = timeNodes
     .map(node => node.dataset.time)
     .map(timeCode => {
       const [mins, secs] = timeCode.split(':').map(parseFloat);
       return (mins * 60) + secs;
     })
     .reduce((total, vidSeconds) => total + vidSeconds);
    

    seconds에 배열의 값들의 재생시간을 담고,
    재생시간을 :를 기준으로 분, 초로 나눠 분값에 60을 곱해 총 재생 시간을 초단위로 뽑아내 정수로 출력,
    그 뒤에 total에 모든 동영상의 재생시간을 합한 값을 출력한다.

  3. 총 재생시간을 시, 분, 초로 바꿔줌

     let secondsLeft = seconds;
     const hours = Math.floor(secondsLeft / 3600);
     secondsLeft = secondsLeft % 3600;
    
     const mins = Math.floor(secondsLeft / 60);
     secondsLeft = secondsLeft % 60;
    
     console.log(hours, mins, secondsLeft);
    

    secondsLeft에 총 재생시간(초단위)를 담아,
    3600으로 나눈 몫, 즉 시간을 hours에 담고
    나머지를 secondsLeft에 담아 60으로 나눈 몫을 mins에 담고 그나머지를 secondsLeft에 담는다.
    결과적으로 hours,mins,secondsLeft에 총 재생시간이 시, 분, 초 단위로 담기게 된다.

찾아본 내용, 알게된 내용들

reduce - 누산기 역할을 함. 전에도 찾아본건데 또 찾아봄.. 복습이 중요한걸 다시 깨달았다.

'개발 > JavaScript30' 카테고리의 다른 글

20. Native Speech Recognition  (1) 2017.04.17
19. Webcam Fun  (0) 2017.04.17
18. Adding Up Times with Reduce  (0) 2017.04.16
17. Sort Without Articles  (0) 2017.04.13
16. Mouse Move Shadow  (0) 2017.04.13
15. LocalStorage  (0) 2017.04.13

Sort Without Articles

목표

배열의 내용에서 부사를 제거한 뒤 알파벳 순으로 재배열

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Sort Without Articles</title>
</head>
<body>
  <ul id="bands"></ul>
<script>
const bands = ['The Plot in You', 'The Devil Wears Prada', 'Pierce the Veil', 'Norma Jean', 'The Bled', 'Say Anything', 'The Midway State', 'We Came as Romans', 'Counterparts', 'Oh, Sleeper', 'A Skylit Drive', 'Anywhere But Here', 'An Old Dog'];
</script>
</body>
</html>

과정

  1. 부사를 제거할 수 있는 함수 생성
  2. 배열을 재정렬
  3. 문서에 매핑

코드 분석

  1. 부사를 제거할 수 있는 함수 생성

    function strip(bandName) {
     return bandName.replace(/^(a |the |an )/i, '').trim();
    }
    

    인자로 bandName을 넣으면 내용중 a, the, an 을 공백으로 바꾸고 공백을 제거하는 함수 strip()을 생성

  2. 배열을 재정렬

    const sortedBands = bands.sort((a, b) => strip(a) > strip(b) ? 1 : -1);
    

    sortedBandsbands의 내용을 알파벳 순서대로 재정렬해 담음

  3. 문서에 매핑

    document.querySelector('#bands').innerHTML = sortedBands.map(band => '<li>${band}</li>').join('');
    

    새 배열을 리스트에 하나씩 담아 bands를 id로 갖는 요소에 매핑한다

찾아본 내용, 알게된 내용들

trim() - 데이터에 있는 공백과 탭을 제거하는 메소드

'개발 > JavaScript30' 카테고리의 다른 글

19. Webcam Fun  (0) 2017.04.17
18. Adding Up Times with Reduce  (0) 2017.04.16
17. Sort Without Articles  (0) 2017.04.13
16. Mouse Move Shadow  (0) 2017.04.13
15. LocalStorage  (0) 2017.04.13
14. JavaScript Reference VS Copying  (0) 2017.04.12

Mouse Move Shadow

목표

마우스 움직임에 따라 텍스트에 효과가 적용돼 움직이도록 해보려 함

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Mouse Shadow</title>
</head>
<body>

  <div class="hero">
    <h1 contenteditable>🔥WOAH!</h1>
  </div>
<script>
</script>
</body>
</html>

CSS코드는 뺐음

과정

  1. 함수 생성을 위한 상수 생성
  2. 그림자를 만드는 함수 생성 및 좌표값 기준 설정
  3. 마우스 이동시 그림자의 위치, 색상 설정
  4. 함수 호출

코드 분석

  1. 함수 생성을 위한 상수 생성

    const hero = document.querySelector('.hero');
    const text = hero.querySelector('h1');
    const walk = 500; // 100px
    

    hero에 클래스가 hero인 요소를 담고, texthero중 h1태그를 담고 walk에 500을 담음

  2. 그림자를 만드는 함수 생성 및 좌표값 기준 설정

    function shadow(e) {
     const { offsetWidth: width, offsetHeight: height } = hero;
     let { offsetX: x, offsetY: y } = e;
    
     if (this !== e.target) {
       x = x + e.target.offsetLeft;
       y = y + e.target.offsetTop;
     }
    

    가장 위에 선언된 상수는 아래 두줄을 한줄로 합친것과 같다

    const { offsetWidth: width, offsetHeight: height} = hero
    const width = hero.offsetWidth
    const height = hero.offsetHeight
    

    width에 hero의 가로길이, height에 hero의 세로길이를 담고(border까지의 길이)
    x,y에 현재 요소를 기준으로 마우스 위치의 절대좌표를 담는다
    조건문의 조건을 해석해보면 현재 마우스의 위치가 <div class="hero">안의 h1태그 위에 있을때 참임을 반환한다는 뜻이고 이때 x,y값을 뷰포트를 기준으로 값이 나올 수 있도록 재 설정해준다는 의미이다.
    즉 마우스가 h1태그 위에 있던 없던간에 좌표값(x,y)은 전체 뷰포트를 기준으로 찍힌다.

  3. 마우스 이동시 그림자의 위치, 색상 설정

     const xWalk = Math.round((x / width * walk) - (walk / 2));
     const yWalk = Math.round((y / height * walk) - (walk / 2));
    
     text.style.textShadow = `
       ${xWalk}px ${yWalk}px 0 rgba(255,0,255,0.7),
       ${xWalk * -1}px ${yWalk}px 0 rgba(0,255,255,0.7),
       ${yWalk}px ${xWalk * -1}px 0 rgba(0,255,0,0.7),
       ${yWalk * -1}px ${xWalk}px 0 rgba(0,0,255,0.7)
     `;
    }
    

    xWalkyWalk의 좌표값 기준을 -250에서 250으로 변경해주고
    그림자의 방향을 각각 설정해 총 4개의 그림자가 나오도록 설정해줌

  4. 함수 호출

     hero.addEventListener('mousemove', shadow);
    

    마우스가 움직이면 shadow 함수를 실행

찾아본 내용, 알게된 내용들

contenteditable - 컨텐츠를 수정할 수 있게 해주는 속성

'개발 > JavaScript30' 카테고리의 다른 글

18. Adding Up Times with Reduce  (0) 2017.04.16
17. Sort Without Articles  (0) 2017.04.13
16. Mouse Move Shadow  (0) 2017.04.13
15. LocalStorage  (0) 2017.04.13
14. JavaScript Reference VS Copying  (0) 2017.04.12
13. Slide in on scroll  (0) 2017.04.12

LocalStorage

목표

아이템을 추가하고 리스트를 볼 수 있는 로컬저장소 구현하기

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>LocalStorage</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="wrapper">
    <h2>LOCAL TAPAS</h2>
    <p></p>
    <ul class="plates">
      <li>Loading Tapas...</li>
    </ul>
    <form class="add-items">
      <input type="text" name="item" placeholder="Item Name" required>
      <input type="submit" value="+ Add Item">
    </form>
  </div>

<script>
  const addItems = document.querySelector('.add-items');
  const itemsList = document.querySelector('.plates');
  const items = [];
</script>
</body>
</html>

기능없이 레이아웃만 잡혀있는 코드

과정

  1. 아이템을 추가하는 함수 생성
  2. 추가한 아이템을 리스트로 보여주는 함수 생성
  3. 체크 여부를 저장하는 함수 생성
  4. 함수 호출

코드 분석

  1. 아이템을 추가하는 함수 생성

    function addItem(e) {
     e.preventDefault();
     const text = (this.querySelector('[name=item]')).value;
     const item = {
       text,
       done: false
     };
    
     items.push(item);
     populateList(items, itemsList);
     localStorage.setItem('items', JSON.stringify(items));
     this.reset();
    }
    

    preventDefault() 메소드는 새로운 정보 입력후 이벤트 실행을 막아주는 역할이다.
    text에 텍스트를 새로 입력을 해줬을때 name의 value값을 저장하고 item 객체에 위에서 만든 text 값을 담고, done속성에 false를 담는다
    다음은 빈 배열 itemsitem을 담고
    기존에 추가했던 함수를 리스트로 뽑아 낸 후에 text창 초기화

  2. 추가한 아이템을 리스트로 보여주는 함수 생성

     function populateList(plates = [], platesList) {
     platesList.innerHTML = plates.map((plate, i) => {
       return `
         <li>
           <input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
           <label for="item${i}">${plate.text}</label>
         </li>
       `;
     }).join('');
    }
    

    popilateList 함수에 빈배열 plates를 만들어 내용과 인덱스를 체크박스와 리스트형태로 반환하도록 한다

  3. 체크 여부를 저장하는 함수 생성

     function toggleDone(e) {
     if (!e.target.matches('input')) return; 
     const el = e.target;
     const index = el.dataset.index;
     items[index].done = !items[index].done;
     localStorage.setItem('items', JSON.stringify(items));
     populateList(items, itemsList);
    }
    

    toggleDone 함수에 체크된 항목들은 done 값을 true로 저장해 다시 값을 불러 올 때 체크되어있는 상태로 불러와지도록 함수 생성 및 로컬스토리지에 저장

  4. 함수 실행

    addItems.addEventListener('submit', addItem);
    itemsList.addEventListener('click', toggleDone);
    
    populateList(items, itemsList);
    

    submit을 할 때 아이템이 추가되는 addItem 실행
    click할 때 체크 여부와 done여부가 저장되는 toggleDown 실행
    마지막으로 저장된 아이템 리스트 호출

찾아본 내용, 알게된 내용들

localStorage - 로컬 스토리지 메소드를 사용하기위해 사용, 만료기간이 없는 저장소ㅁ
setItem, getItem - 로컬 스토리지에 내용을 저장, 불러오는 메소드
reset() - value를 초기화 할 때 사용


길기도 길고 복잡해서 여러번 더 봐야 이해할 수 있을 것같음. 완벽히 이해하진 못해서 설명이 부족함..주륵


'개발 > JavaScript30' 카테고리의 다른 글

17. Sort Without Articles  (0) 2017.04.13
16. Mouse Move Shadow  (0) 2017.04.13
15. LocalStorage  (0) 2017.04.13
14. JavaScript Reference VS Copying  (0) 2017.04.12
13. Slide in on scroll  (0) 2017.04.12
12. Key Sequence Detection  (0) 2017.04.11

float을 clear하는 방법(clearfix)

마크업 후에 CSS작업을 하다보면 가장 많이 겪는 순간이 상단 네비게이션바를 만들 때 float속성으로 원하는 곳에 배치를 하면 그 다음에 오는 태그들의 위치가 뭉개지는 경우가 허다한데
원래 float 뒤에 포지션이 뭉개지는 현상은 브라우저상의 오류로 생겨난 것이고, 이를 해결하는 clearfix는 위의 오류를 해결하기 위해 똑똑한 분들이 만들어낸 일종의 버그해결 방법이다.

clearfix의 네 가지 방법

  1. 가상 요소 ::after 사용(권장)
  2. overflow속성 사용
  3. 빈 엘리먼트로 clear속성 적용
  4. float로 대응

하지만 1번 방법만 알고 사용하면 되기 때문에 나머지는 간략하게 설명하겠음

1. 가상 요소 ::after 사용

우선 가상 선택자가 무엇인지 알아보면,
가상 클래스(class)와 가상 요소(element)를 편의상 함께 칭할 때 사용하며, 정식 명칭은 아님.

가상 클래스(Pseudo-class)는 요소에 직접적으로 클래스를 부여하지는 않았지만, 요소의 상태에 따라서 클래스를 적용한 것처럼 효과를 다르게 줄 수있다.
가장 많이 쓰는 예시는 a태그의 효과를 바꾸기 위해 a:hover, a:link 이고, 이때 a뒤에 쓰인 :hover, :link를 가상 클래스라고 한다.

가상 요소(Pseudo-elements)는 말 그대로 가상의 요소를 만들고 내용을 넣어 출력하겠다는 것이다. 보통 ::after, ::before을 자주 사용한다.

CSS2.1에서는 가상 클래스와 가상 요소 모두 싱글콜론(:)을 사용했지만, CSS3 부터는 둘을 구분하기 위해 가상 클래스는 싱글콜론(:), 가상 요소는 더블콜론(::)을 사용한다.

그럼 ::after로 어떻게 clearfix를 하는지 알아보면
float 속성을 적용한 요소의 부모요소에 ::after를 사용해주면 된다.
예시로 nav태그 안에 h1태그는 float: left, ul태그에 float: right가 적용되어 있다면, 다음과 같이 작성해주면 된다.

nav::after {
    content: '';
    dispaly: table;
    clear: both
}

무슨 뜻인지 알아보면
nav 태그 뒤에 내용이 빈(content: '') 테이블을(display: table) 만들고, float: left, float: right를 초기화 시키겠다는 뜻이다.
이렇게 작성을 해주면 nav태그 뒤에 다른 내용을 작성을 하면 위로 딸려올라가지 않고 nav태그 다음에 위치하게 된다.

여기서 display: table 대신 display: block을 쓰는 것도 가능하고,
clear: left를 쓰면 float: left를, clear: right를 쓰면 float: right를 초기화 한다는 뜻인데 항상 clear: both를 사용해도 상관이 없다.

2. overflow속성 사용

위와 마찬가지로 float를 가진 요소의 부모 요소에 overflow: hidden 또는 overflow: auto를 적용시켜주면 된다.
overflow: auto 사용시 자식의 너비가 부모의 너비보다 크다면 가로 스크롤바가 생기고,
overflow: hidden의 경우 넘치는 부분이 잘리기 때문에 사용하지 않는것이 좋음.

3. 빈 엘리먼트로clear속성 적용

1번에 설명한것과 비슷한 개념인데 위에서는 가상 요소를 사용했지만 이 방법은 빈 태그를 만들어 클래스에 clear: both; height: 0; overflow: hidden;을 적용해 높이가 0인 보이지 않는 태그를 만들어 clear: both float를 해제하는 방법인데, 의미없는 태그를 만들어 사용하는 것이므로 사용하지 않는것이 좋음.

4. float로 대응

float속성을 가진 자식요소의 부모요소에 똑같이 float를 적용해 주는 방법인데 반응형 웹에 적합하지 않으므로 사용하지 않는것이 좋음

결론

그냥 1번빼고 다른것은 ‘이런게있구나~’ 하고 넘기고 1번만 잘 사용할줄 알면 문제없이 포지셔닝의 고수가 되어있을 것이다!
그리고 이러한 모든 고민은 flex-box를 사용하면 부질없는 행동이었음을 다시한번 깨닫기 때문에, flex-box를 공부해 사용하는것을 추천!(다음에 포스팅 해보도록 하겠습니다)

'개발 > CSS' 카테고리의 다른 글

CSS 포지션(position)  (0) 2017.10.12
CSS 디스플레이(display)  (0) 2017.10.12
CSS 박스모델(box-model)  (0) 2017.10.12
CSS reset  (0) 2017.06.09
CSS flex-box 재미있게 익히기  (0) 2017.04.24
CSS / float를 clear하는 방법 네가지(clearfix)  (5) 2017.04.13
  1. 정은지 2019.04.01 12:21

    1번에 설명에서 dispaly오타있네요ㅎ 정보 감사합니다 덕분에 해결햇어요~

  2. GG맨 2019.04.19 10:47

    고맙읍니다

  3. 사비향 2019.10.24 16:43

    이건 부모요소안에 넣는거고 같은 자식요소끼리는 clear:botn;인건가요?

JavaScript References VS Copying

목표

스크롤이 이미지 자리의 중간까지 오면 이미지가 양옆에서 날아오는 효과를 적용하려 함

기본 코드

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JS Reference VS Copy</title>
</head>
<body>
  <script>
        const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];
  </script>
</body>
</html>

기본 코드가 전부 주석으로 필요한 코드만 남기고 다 지웠음

과정

  1. 변수 설정
  2. 이미지를 날아오게 할 함수 생성
  3. 함수 호출

코드 분석

  1. 문자열, 숫자열, 불린일 때 변수 선언 및 변경

     // start with strings, numbers and booleans
    let age = 100;
    let age2 = age;
     console.log(age, age2); // 100, 100 출력
     age = 200;
     console.log(age, age2); // 200, 100 출력
    

    문자열, 숫자열,불린에서는 위와 같이 선언했던 변수에 다른 값을 넣으면 변경되어 출력된다.

  2. 배열일 때 변수 선언 및 변경

     // Let's say we have an array
     const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];
     const team = players;
    
     console.log(players, team);
     // ['Wes', 'Sarah', 'Ryan', 'Poppy'],['Wes', 'Sarah', 'Ryan', 'Poppy']
    
     team[3] = 'Lux';
     console.log(players, team);
     // ['Wes', 'Sarah', 'Ryan', 'Lux'],['Wes', 'Sarah', 'Ryan', 'Lux']
    

    분명히 team[3]으로 team의 배열만 바꾸고 싶었는데 결과는 players도 함께 바뀌게 된다.
    이를 해결하기 위해서는 아래와 같이 사용할 수 있다.

     //해결방법 1 - slice()
     const team2 = players.slice();
    
     //해결방법 2 - concat()
     const team3 = [].concat(players);
    
     //해결방법 3 - [...](spread operator)
     const team4 = [...players];
    
     //해결방법 4 - Array.from()
     const team5 = Array.from(players);
    

    위의 네가지의 방법으로 새로운 배열을 만들어 기존 배열의 변경 없이 따로 값을 변경할 수 있다.

  3. 객체일 때 변수 선언 및 변경

     // with Objects
     const person = {
         name: 'Wes Bos',
         age: 80
     };
     const captain = person;
     captain.number = 99;
    
     console.log(person) // {name: 'Wes Bos', age: 80, number: 99}
    

    배열과 마찬가지로 원래의 객체 또한 변경이 된다.
    이를 해결하기 위해서는 아래와 같이 사용 할 수 있다.

     //해결방법 1 - Object.assign({}, 참조객체, 추가할값)
     const cap2 = Object.assign({}, person, { number: 99, age: 12 });
    
     //해결방법 2 - {...}
     const cap3 = {...person};
    

    위의 방법으로는 아래 코드에서 social안의 twitter내용을 변경할 수 없기 때문에 JSON을 아래와 같이 사용

     const wes = {
         name: 'Wes',
         age: 100,
         social: {
             twitter: '@wesbos',
             facebook: 'wesbos.developer'
         }
     };
     const dev2 = JSON.parse(JSON.stringify(wes));
     dev2.social.twitter = 'Hi'
    

    찾아본 내용, 알게된 내용들

slice() - 배열의 복사본을 생성
concat() - 값들을 연결할 때 사용
assign() - 열거할 수 있는 객체를 복사할 때 사용

'개발 > JavaScript30' 카테고리의 다른 글

16. Mouse Move Shadow  (0) 2017.04.13
15. LocalStorage  (0) 2017.04.13
14. JavaScript Reference VS Copying  (0) 2017.04.12
13. Slide in on scroll  (0) 2017.04.12
12. Key Sequence Detection  (0) 2017.04.11
11. Custom Video Player  (0) 2017.04.10

+ Recent posts