CSS&JS/👀Study and Copy

1분코딩 - BBC 인터랙티브 클론코딩

arancia_ 2021. 12. 27. 11:25

2022년 1월달에 three.js 강의도 만들어주실것 같다~~ 쵝오~~!

인프런에서 1분코딩님이 제공하는 무료강의 : BBC 인터랙티브 페이지 클론 코딩하기 복습

(원본 BBC 사이트 바로가기)

 

메모

  • Intersection Observer가 관찰하는 대상이 화면 높이보다 작거나 크면 잘 관찰되지만, 딱 100vh일땐 씹고 넘어가는 현상을 왕왕 봄 0_0;;자바스크립트가 똑같은 코드인데도 기본 Intersection Oberserver가 등신같이 군다면 CSS를 확인해보자...
  • 클래스를 추가하고 제거할 때 번쩍거리는 현상을 어떻게 해결할까.. prev로 저장해서 해보기도 했지만 꼬여서 결국 그냥 css transition delay값을 조정하였다. 원본일때와 visible 모드일때 transition delay값을 다르게 조정해주면 된다. (visible모드일때 transition delay값을 0s로 주면 됨)

나중에 필요할때 빠르게 참조할겸 골자만 가져왔습니다.
꼭 원본 강의를 들어보세요 ~_~!!!

 

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="ko">
<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>BBC 인터랙티브 복습</title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
<script src="./js/main.js" type="module"></script>
</head>
<body>
 
<header class="wrap">
    <h1>코로나19가 바꿀 사무실의 미래</h1>
    <div>1분 코딩 강의 바로 가기 : <a href="https://www.inflearn.com/course/bbc-인터랙티브웹-클론/dashboard" target="_blank">BBC 인터랙티브 페이지 클론 코딩</a></div>
    <div><a href="https://www.bbc.com/korean/resources/idt-48d3c9a7-4063-4289-9726-611b5ea9d7b5" target="_blank">사이트 링크</a>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quas qui eos deleniti maxime culpa magni officia voluptate. Nemo, inventore quod.</div>
</header>
 
<section id="sect_scroll">
    <ul id="bg">
        <li class="item-bg"><div>0</div></li>
        <li class="item-bg"><div>1</div></li>
        <li class="item-bg"><div>2</div></li>
        <li class="item-bg"><div>3</div></li>
        <li class="item-bg"><div>4</div></li>
        <li class="item-bg"><div>5</div></li>
    </ul>
 
    <ul id="txt">
        <li class="item-txt">
            <div class="box-txt">0-AAA</div>
        </li>
        <li class="item-txt">
            <div class="box-txt">1-BBBBB</div>
        </li>
        <li class="item-txt">
            <div class="box-txt">2-CCCCCCC</div>
        </li>
        <li class="item-txt">
            <div class="box-txt">3-DDDDDDDDD</div>
        </li>
        <li class="item-txt">
            <div class="box-txt">4-EEEEEEEEEEE</div>
        </li>
        <li class="item-txt">
            <div class="box-txt">5-FFFFFFFFFFFFF</div>
            <div class="box-txt">5-FFFFFFFFFFFFF</div>
            <div class="box-txt">5-FFFFFFFFFFFFF</div>
        </li>
    </ul>
</section>
 
<footer class="wrap">
    <h3>End of Scroll...</h3>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium nemo eos necessitatibus, natus nam non sunt repellat inventore optio sequi.</p>
    <h3>End of Scroll...</h3>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium nemo eos necessitatibus, natus nam non sunt repellat inventore optio sequi.</p>
    <h3>End of Scroll...</h3>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium nemo eos necessitatibus, natus nam non sunt repellat inventore optio sequi.</p>
</footer>
 
</body>
</html>
cs



CSS

Intersection Obersever가 감지해야하는 DOM의 높이는 딱 100vh가 되지 않게 유의하자.. ??? (원인모름)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@charset "utf-8";
:root{
    --wid:680px;
}
*{margin:0;padding:0;box-sizing:border-box;}
li{list-style-type:none;}
html,body{width:100%;min-height:100vh;}
 
.wrap{
    position:relative;
    width:100%;max-width:var(--wid);
    margin:0 auto; padding:80px 20px;}
 
#sect_scroll{ 
    position:relative;
    width:100%; max-width:1200px;
    margin:0 auto;}
 
#bg{
    position:sticky;
    top:0;
    width:100%; 
    height:100vh;
}
 
.item-bg{
    display:flex;justify-content:center;align-items:center;
    position:absolute;
    top:0;left:0;
    width:100%;height:100vh;
    font-size:20vw;
    background:rgb(
        calc(var(--i) * 30),
        calc(var(--i) * 40),
        calc(var(--i) * 50));
    color:#fff;
    opacity:0;
    transition:opacity .3s .6s;}
 
    .item-bg.on{
        opacity:1;
        transition:opacity .3s 0s;
    }
 
#txt{
    position:relative;
    width:var(--wid);
    margin:0 auto;padding:0 20px;}
 
.item-txt{
    position:relative;
    width:100%;
    padding-bottom:60vh;}
 
.box-txt{
    position:relative;
    width:100%;
    padding:2rem;
    margin-bottom:10px;
    background:rgb(255,255,255,.8);
    border:1px solid #d2d2d2;
    border-radius:14px;
}
 
/* footer */
 
cs



main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { auto_dataset } from "./auto_dataset.js";
import { init_scroll } from "./scroll.js";
 
//1.data-set으로 dix먼저 지정해주고, var(--i)도 설정해주고
auto_dataset();
 
//2.scroll과 intersection oberver 준비
init_scroll();
 
//3.새로고침시 강제
window.addEventListener('load',()=>{
    setTimeout(()=>{window.scrollTo(0,0)},100);
    //scrollTo는 그냥 바로 걸면 안될때가 있어서
})
cs

auto_dataset.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export function auto_dataset(){
    const bg = document.getElementById('bg');
    const all_item_bg = bg.children;
    const txt = document.getElementById('txt');
    const all_box_txt = txt.children;
 
    Array.prototype.forEach.call(all_item_bg,(elem,idx)=>{
        if(idx==0){elem.classList.add('on');}
        elem.dataset.idx = idx;
        all_box_txt[idx].dataset.idx = idx;
        elem.style.setProperty('--i',idx);
    });
    //또는 Array.from(all_item_bg).forEach(...);
}//auto_dataset
cs

scroll.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const item_bg = document.getElementsByClassName('item-bg');
const item_txt = document.getElementsByClassName('item-txt');
let winHei;
let currIDX;
let currItem = item_bg[0];
 
/* ---- 초기 세팅 ----- */
export function init_scroll(){
    winHei_minmax();
    new_io();
    window.addEventListener('resize',winHei_minmax);
    window.addEventListener('scroll',on_scroll);
}//init_scroll
 
/* Intersection Observer */
function new_io(){
    const io = new IntersectionObserver((ent,obs)=>{
        currIDX = ent[0].target.dataset.idx;
        currItem = item_bg[currIDX];
        // console.log(currIDX);
    });
    Array.from(item_txt).forEach(elem=>{io.observe(elem)});
}//new_io
 
/* Scroll */
function on_scroll(){
    for(let i=currIDX-1; i<=currIDX+1; i++){
        //0. 이전,현재,다음 아이템
        const comp = item_txt[i];
        if(!comp){continue;}
 
        //1.top위치 비교
        const {min,max} = winHei;
        const tTop = comp.getBoundingClientRect().top;
        if(tTop >= min && tTop <= max){
            if(currItem){remove_on(currItem);}
            currItem = item_bg[i];
            add_on(currItem);
        }//if
    }//for
}//on_scroll
 
/* Add,Remove Class */
function add_on(elem){elem.classList.add('on');}
function remove_on(elem){elem.classList.remove('on');}
 
/* get Window innerHeight */
function winHei_minmax(){
    winHei = {
        min : window.innerHeight * .1,
        max : window.innerHeight * .9,
    };
}//winHei_minmax
 
cs