금융프로젝트

[국민 은행 클론코딩][vue]메인 슬라이드

h-yujin 2022. 11. 10. 16:34

목표 화면

구현한 화면

컴포넌트 구조

headerWrap.vue에 대해서는 전 기록물에 있다.

ActiveWrap.vue

  • template
 
<template>
    <div class="wrap-visual active1">
        <div class="area-con">
            <ul>
                <li class="section section1">
                    <div>
                        <strong><img src="https://www.kbstar.com/2018/img/visual/visual_section79_v2_tit01.png"></strong>
                        <span>
                            <img src="https://www.kbstar.com/2018/img/visual/visual_section79_v2_tit02_2.png">
                        </span>
                    </div>
                </li>
            </ul>
        </div>
    </div>
    <div class="wrap-visual active2"></div>
    <div class="wrap-visual active3"></div>
    
</template>

section section1 클래스는 opacity:0,visiblity:hidden으로 로드 직 후에는 보이지 않는 상태다.

이 클래스에 opacity:1,visiblity:visible인 style속성을 가지는 ‘on’이라는 style속성을 부여해야한다.

  • style
.wrap-visual .area-con > ul > li {
    position: absolute;
    left: 0;
    top: 0;
    opacity:0;
    z-index:-1;
    color: #333;
    visibility: hidden;
}
.wrap-visual .area-con > ul > li.on {
    z-index: 0;
    visibility: visible;
    opacity: 1;
}
  • script
setTimeout(() => {
    document.querySelector(".area-con ul").childNodes.forEach(n=>{
        n.className+=" on";
    });
}, 1000);

페이지가 로드된 후 1초 후에 해당 태그에 ‘on’이라는 클래스를 부여했다.

주의할 점은 className+=”[띄어쓰기]on”이라는 점이다. 꼭 띄어쓰기를 해야한다.

해당 클래스의 자식 태그인 strong과 span 또한 opacity가 0이므로 1로 변경해 주어야 한다.

여기서 움직이는 효과를 더하기 위해 marginLeft도 변경해준다.

  • style
.wrap-visual .area-con > ul > li > div > strong {
    display: block;
    font-size: 40px;
    line-height: 52px;
    font-weight: normal;
    letter-spacing: -4px;
}
.wrap-visual .area-con > ul > li > div > span {
    font-size: 19px;
    line-height: 28px;
    color: #5c5c5c;
}
.wrap-visual .area-con > ul > li > div > span, .wrap-visual .area-con > ul > li > div > strong, .wrap-visual .area-con > ul > li > div > a.link {
    display: block;
    opacity: 0;
    margin-left: 30px;
    -webkit-transition: all 0.6s;
    transition: all 0.6s;
}
  • script
setTimeout(() => {
    document.querySelector(".area-con ul").childNodes.forEach(n=>{
        n.className+=" on";
       
        n.childNodes[0].childNodes.forEach(h=>{
            h.style.opacity="1";
            h.style.marginLeft="20px";
        })
    });
}, 1000);

초기 margin-left값이 30px에서 20px로 -10px이동한다.

:before :after 활용 슬라이드

클래스 ‘on’이 부여되면서 section section1클래스의 :before, :after속성에 부여된 백그라운드이미지를 보여줘야한다. 두 가상 태그 또한 opacity:0이므로 초기에는 보이지 않는다.

  • 초기 style
.wrap-visual .area-con > ul > li:before, .wrap-visual .area-con > ul > li:after {
    content: '';
    display: block;
    position: absolute;
    right: 30px;
    bottom: -40px;
    width: 640px;
    height: 401px;
    opacity: 0;
    -webkit-transition: all 1.5s;
    transition: all 1.5s;
}
.wrap-visual .area-con > ul > li.section1:before {
    background: url(../assets/visual_section79_1.png) no-repeat 100% 0;
}

.wrap-visual .area-con > ul > li.section1:after {
    background: url(../assets/visual_section79_2.png) no-repeat 100% 0;
}
.wrap-visual .area-con > ul > li:after {
    bottom: 0;
    opacity: inherit;
}
  • 클래스 ‘on’이 부여된 후 style
.wrap-visual .area-con > ul > li.on:before {
    bottom: 0;
    opacity: 1;
}

이렇게 ‘on’에 가상 태그 before를 붙여주어 애니메이션을 구현할 수 있다.

전체 코드

  • ActiveWrap.vue
 
<template>
    <div class="wrap-visual active1">
        <div class="area-con">
            <ul>
                <li class="section section1">
                    <div>
                        <strong><img src="https://www.kbstar.com/2018/img/visual/visual_section79_v2_tit01.png"></strong>
                        <span>
                            <img src="https://www.kbstar.com/2018/img/visual/visual_section79_v2_tit02_2.png">
                        </span>
                    </div>
                </li>
            </ul>
        </div>
    </div>
    <div class="wrap-visual active2"></div>
    <div class="wrap-visual active3"></div>
    
</template>

export default {
  name: 'ActiveWrap',
methods:{
},
}
setTimeout(() => {
    document.querySelector(".area-con ul").childNodes.forEach(n=>{
        n.className+=" on";
       
        n.childNodes[0].childNodes.forEach(h=>{
            h.style.opacity="1";
            h.style.marginLeft="20px";
        })
    });
}, 1000);
  • ContentWrap.vue
<template>
    <div id="content">
      <active-wrap></active-wrap>
    </div>
</template>
<script>
import ActiveWrap from './ActiveWrap.vue';

export default {
  components: { ActiveWrap },
  name: 'ContentWrap',
  
}
</script>
<style>
#content{
  min-height: calc(100vh - 220px);
    margin: -70px auto 0;
    padding: 0 0 55px;
}
</style>
  • App.vue
<template>
  <div class="wrapAll">
    <header-wrap></header-wrap>
    <content-wrap></content-wrap>
  </div>
</template>

<script>
import ContentWrap from './components/ContentWrap.vue';
import HeaderWrap from './components/HeaderWrap.vue';

export default {
  name: 'App',
  data:()=>{
    return {
      number:0
    }
  },
  methods:{
    addNumber(){
      this.number++;
    }
  },
  components:{
    HeaderWrap,
    ContentWrap
  }
}
</script>

<style>

#app {
  color: #5a5a5a;
    font-size: 0.875em;
    line-height: 1.5;
    font-family: '맑은 고딕', 'Malgun Gothic','돋움',Dotum,AppleSDGothic,Tahoma,Helvetica,sans-serif;
    height: 100%;
    display: block;
}
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, strong, sub, sup, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, embed, input, select, textarea, button{
  margin: 0;
    padding: 0;

}
h1, h2, h3, h4, h5, h6{
  font-size: 1em;
    font-family: '맑은 고딕', 'Malgun Gothic','돋움',Dotum,AppleSDGothic,Tahoma,Helvetica,sans-serif;
}
a, em, label, span, strong, button{
  display: inline-block;
}
a{
  cursor: pointer;
}
a:visited{

  color: #5a5a5a;
    text-decoration: none;
}
h1{

  font-weight: bold;
}
ul {
    display: block;
    list-style-type: disc;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    padding-inline-start: 40px;
}
li {
    display: list-item;
    list-style-type: none;
    text-align: -webkit-match-parent;
}
</style>