CSS&JS/⚡Thinkers

clipText

arancia_ 2022. 7. 25. 13:19

깃허브

 

GitHub - OhIkmyeong/cliptext: clipText-intersectionObserver

clipText-intersectionObserver. Contribute to OhIkmyeong/cliptext development by creating an account on GitHub.

github.com

 

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
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>텍스트 테스트</title>
    <link rel="stylesheet" type="text/css" href="./css/reset.css"/>
    <link rel="stylesheet" type="text/css" href="./css/scrollText.css"/>
<script src="js/main.js" type="module"></script>
</head>
<body>
    <div id="wrapper">
        <div class="clipText">
            <p style="font-size:10vmax;">ClipText</p>
            <p>version 1.0</p>
        </div>
        <div class="clipText">
            <p>Hello World</p>
            <p>Nice to Meet you!</p>
        </div>
        <div class="clipText">
            <p>clipText 안의 p태그 안의 글자를</p>
            <p>span 태그로 자동 분리하여</p>
            <p>setProperty로 transition에</p>
            <p>delay를 부여합니다.</p>
        </div>
        <div class="clipText">
            <p>Intersection Observer로 어쩌고 저쩌고...</p>
            <p>문장이 너무 길어지지 않도록 주의</p>
        </div>
        <div class="clipText">
            <p>Have Fun!!</p>
        </div>
        <div class="clipText">
            <p>더이상 쓸 말이 없다...</p>
        </div>
    </div><!-- wrapper -->
</body>
</html>
cs

CSS

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
@charset "utf-8";
#wrapper{
    display:flex; flex-flow:column nowrap;
    justify-content:center; align-items:center;
    gap:50vmax;
    position:relative;
    padding:50vmax 0;
}
 
/* [clipText] */
.clipText{
    display:flex; flex-flow:column nowrap;
    gap:20px 0;
    position:relative;
    text-align:center; font-size:5vmin; font-weight:bold; letter-spacing:-.03em;
    text-transform:uppercase;}
 
    .clipText p{
        position:relative; overflow:hidden;
        padding:0 1em;
        line-height:1;
        background:rgb(66, 77, 106); color:#fff;}
 
    .clipText p span{
        display:inline-block;
        position:relative;
        transform:translateY(100%);
        transition:transform .3s 0s;
    }
    .clipText.on p span{
        transform:translateY(0);
        transition:transform .3s var(--delay);
    }
cs

main.js

1
2
3
4
5
6
7
8
9
10
11
import { SplitText } from "./splitText.js";
const $$clipText = document.querySelectorAll('.clipText');
$$clipText.forEach($clipText => new SplitText($clipText));
 
const IO = new IntersectionObserver((entries,observer)=>{
    const TARGET = entries[0].target;
    const bool = entries[0].isIntersecting;
    TARGET.classList.toggle('on',bool);
},{threshold : 0.15})
 
$$clipText.forEach($clipText => IO.observe($clipText));
cs

splitText.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
export class SplitText{
    constructor($clipText){
        this.$clipText = $clipText;
        this.init();
    }//constructor
    /* 실행 */
    init(){
        const $$p = this.$clipText.querySelectorAll('P');
        const len = $$p.length;
        let start = 0;
        $$p.forEach(($p,pIdx) => {
            $p.innerHTML = $p.textContent.replace(/\S/g, "<span>$&</span>");
            const $$span = $p.querySelectorAll('span');
            let sec;
            $$span.forEach(($span,sIdx) => {
                sec = ((len * pIdx + sIdx) * 0.05 + start).toFixed(2);
                $span.style.setProperty("--delay",`${sec}s`);
            });
            start += Number(sec) - (len / 5);
        });
    }//init
}//class-SplitText
cs