
라인 주식회사(LINE Corporation)는 커뮤니케이션 앱 라인(LINE)을 기반으로 커뮤니케이션, 콘텐츠, 엔터테인먼트, 광고 사업 등 모바일에 특화된 서비스를 개발 및 운영하고 있습니다. 이외에도, 핀테크와 AI 사업 등 다양한 분야로 진출하고 있습니다. 라인은 자사 미션인 ‘클로징 더 디스턴스(Closing the Distance)’를 바탕으로 전 세계를 대상으로 라인 서비스를 전개하고 있습니다.
▪️ header + main
라인의 슬로건을 메인 화면에 배치하며, 'LINE'이라는 서비스의 색깔을 잘 보여줄 수 있는 영상을 loop로 반복재생함. (동영상은 라인의 홈페이지를 참고하여 직접 편집하여 사용함) 메뉴 네비게이션과 메뉴를 함께 배치하여 사용자가 원하는 서비스를 사용할 수 있도록 배치함
▪️ menu
큰 구성은 회사 / 서비스 / 보도자료 / 채용으로 기존의 라인 메뉴 구성과 유사하게 배치함. 왼쪽에는 회사에 대한 기본 정보 및 언어 전환 (영문 버전은 클릭시 준비중입니다. 라는 알림창), sns로 간결한 배치
▪️ LIFE ON LINE (effect01)
라인의 대표 슬로건인 'LIFE ON LINE'을 메인 화면 다음에 배치하여, 스크롤에 따라 글자가 움직이도록 gsap효과 부여. 기존 라인의 웹페이지와 다르게 효과를 중심으로 it기업의 트렌디한 느낌을 강조하고자 함
▪️ result
라인이라는 기업 및 서비스가 이뤄낸 성과를 강조하여, 지금까지 걸어온 길들을 사용자가 한 눈에 볼 수 있게 구성함. 스크롤에 따라 배치된 방향에서 등장하는 감각적인 효과를 부여함
▪️ service
라인이 대표적으로 제공하는 서비스를 보여줌. 서비스를 보여주는 부분은 되도록 깔끔하고 직관적으로 볼 수 있게 가장 베이직한 구성을 선택함. 이미지와 버튼에 hover을 부여해 너무 단조롭지않게 구성함
▪️ LINER INTERVIEW (effect02)
현재(2022.09 기준) 하반기 신입 공개채용을 가장 큰 이벤트로 하고 있기 때문에, 라인 재직자들의 인터뷰를 구성해 각 직군의 종사자들의 인터뷰를 제공하고자 함. effect01과 같이 스크롤시 글자가 움직이도록 하며, 인터뷰 박스가 스크롤에 맞춰 나오는 효과를 위주로 구성함. 각각 인터뷰 hover시 해당 인터뷰이의 사진이 보여지도록 함.
▪️ news
라인의 최신 동향을 알 수 있는 뉴스 페이지를 가장 하단에 구성하여, 가장 기본적인 swiper형식으로 카드뉴스와 같이 구성함. hover시 padding으로 색상을 부여해 너무 단조롭지 않게 구성.
- index.html : 마크업
- asset
1) css : watch sass -> css
2) font : 사용 폰트
3) image : 사용 이미지
4) js
- main.js
5) scss :- abstracts
- _mixins.scss : 미디어쿼리/말줄임
- base
- _preset.scss : common
- _reset.scss : reset
- _typo.scss : font
- layout
- _footer.scss : footer
- _header.scss : header
- pages
- _index.scss : main
- vender
- _swiper.scss : swiper 링크
- style.scss : @import
clamp()는 최소/최대 값 범위 사이의 값을 표현할 수 있는 경우 사용
선호값은 기본값으로 vw로 작성한다.
ex) fontsize : clamp(35px, 6vw,100px)
🧐 vw로 작성하는 이유?
상대값이기 때문에, px와 같은 절대 단위를 사용하면 clamp함수 기능을 할 수 없다.
최소보다는 작아질 수 없고, max보다는 커질 수 없는 가변값이다.
🧐 vw값을 구하는 방법?
vw계산기를 사용한다.
scss에서 미디어쿼리를 사용할 때, mixin을 사용하여 코드를 정리하면 편하게 사용 가능하다
/*반응형 화면 크기 변수 설정*/
$mobile: 767px; //320
$tablet: 1023px; // 768
$desktop: 1200px; //1024
/*반응형, 브라우저 크기가 767px 이하일때*/
@mixin mobile{
  @media (max-width: $mobile){
    @content;
  }
}
/*반응형, 브라우저 크기가 768이상, 1023px 이하일때*/
@mixin tablet{
  @media (max-width: $tablet){
    @content;
  }
}
/*반응형, 브라우저 크기가 1024px 이상일때*/
@mixin desktop{
  @media (max-width: $desktop){
    @content;
  }
}🧐 Mixin이란?
‘믹스인’은 재사용 가능한 기능을 만드는 방식을 의미한다.
- 선언하기 :
@mixin- 사용하기 :
@include
📁abstract
실제 스타일은 없고, 그저 다른 폴더에 정의된 스타일을 돕는 역할
글로벌 변수, 함수는 _variables 파일 / mixins은 _mixins에 작성
📁base
사이트 전반에 걸쳐서 재사용되는 스타일 정의
사이트 전반에 사용될 폰트, 디폴트 스타일 등
📁components
사이트 내에서 재사용가능한 작은 부분들을 정의
layout과 유사하지만, 작은 요소들을 정의한다는 것에서 차이점이 있음
buttons, forms 등 겹치는 요소
📁layout
사이트 구조에 해당하는 레이아웃 정의
headers, footers 등
📁pages
각 페이지에서 사용될 구체적인 스타일
main 페이지 등
🖇️style.scss
폴더에 따라 분류한 scss파일들을 한 군데에 모을 hub 역할
모든 파일을 import해준다.
import만 담당하는 폴더이기 때문에 다른 파일들과 달리 _을 하지 않아야 한다.
상위 선택자의 반복을 피하고 좀 더 편리하게 복잡한 구조를 작성 가능
.sc-main {
  width: 100%;
  .main-list {
    display : flex;
    .main-item {
      margin : 10px;
    }
  }
}&을 사용하여, 부모 선택자를 참조할 수 있음
.btn-nav {
  position: absolute;
  &.active {
    color: #fff;
  }
}이는 btn-nav.active와 같다.
.loading{
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background: #06c755;
    z-index: 500;
    .load-img{
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        overflow: hidden;
        img{width: 250px;}
    }
}gsap.to('.loading',{ delay:1.2, opacity:0, display:'none', height:0, onComplete:function(){ intro.play() } })로딩 전체화면에 delay:1.2를 부여해, 1.2초동안 로딩화면 재생
숨겼다가->재생도되록gsap.to('.loading img',{ delay:0.8, opacity:0, onComplete:function(){ intro.play() } })라인 아이콘은 0.8초동안 재생되도록 보였다가->안보이게
mainTxt = gsap.timeline({}) const intro = gsap.fromTo('.sc-main .title-area .word',{ yPercent:100, opacity:0 },{ yPercent:0, stagger:0.5, opacity:1, paused:true })로딩화면이 끝난 후, 메인이미지의 텍스트 효과 부여하기
로딩이 끝날 때 까지 멈췄다가, 0->1로 보여지면서 아래에서 위로 올라오는 효과
$('.btn-menu').click(function(e){ 
    e.preventDefault(); 
    
    if($(this).hasClass('active')){
      $('body, .group-menu, .btn-menu').removeClass('active'); 
      $(this).find('.blind').text('메뉴열림');
    }else{
      $('body, .group-menu, .btn-menu').addClass('active'); 
      $(this).find('.blind').text('메뉴닫힘')
    }
  });
btn-menu 메뉴를 클릭했을 때,
  var FirstScroll = 0;
  var prevScrollTop = $(window).scrollTop(),
    curr = $(window).scrollTop(); //브라우저 스크롤했을때 위치
 
  $(window).scroll(function(e){
    e.preventDefault();
    curr = $(this).scrollTop(); //= window scrollTop
//반대스크롤시 보이게
    if ( curr < prevScrollTop ){ //반대스크롤하면
      $(".group-header").addClass('active'); //메뉴보여짐
      $(".group-header").removeClass('hide'); //헤더숨김
      if(curr >= 100){ //+curr이 100보다 크거나 같다면
        $('.group-header').addClass('active'); //메뉴보이게
      }else{
        $('.group-header').removeClass('active'); //아니라면 메뉴 안보이게
      }
//스크롤시 사라지게
    } else if( curr > prevScrollTop ) { //스크롤탑위치에서 스크롤해서 내려가면
      $(".group-header").removeClass('active'); //메뉴도 없애면서
      $(".group-header").addClass('hide'); //헤더 숨김
    }
    prevScrollTop = curr;
  });&::before{ 
    content: '';
    width: 100px; height: 100px;
    position: absolute;
    top: 0;right: 0;
    background: #06c755;
    transform: scale(0);
    border-radius: 50%;
    transition: 1s;
}
&.active{visibility: visible;
opacity: 1;
    &::before{
        transform: scale(50);
    }
} group-menu에 before을 만들어, 검은 동그라미 생성
scale을 0으로 한 뒤, active가 되었을 때 함께 transform scale50으로 동그랗게 퍼져가는 모양 생성
group-menu의 텍스트들보다 z-index가 낮아야 함
<li class="result-item" data-x ="-20"> 
    <p class="sort">월간 이용자 수</p>
    <div class="img-area">
        <em class="num">2억명</em>
        <div class="img-box">
            <img src="./assets/image/result1.jpg" alt="월간 이용자 수">
        </div>
    </div>
</li>
<li class="result-item right" data-x ="20">
    <p class="sort">다운로드 수</p>
    <div class="img-area">
        <div class="img-box">
            <img src="./assets/image/result2.jpg" alt="다운로드 수">
        </div>
        <em class="num point">5억회</em>
    </div>
</li> x축 기준으로 오른쪽, 왼쪽에서 li들이 나올 수 있게 구성할 것이기 때문에
data-x를 음수 양수 번갈아서 배치함
데이터 수치를 넣어놔야 컨트롤이 가능함.
const result = document.querySelectorAll('.sc-result .result-item');
result.forEach(el=>{
  xVal = (el.dataset.x) ? el.dataset.x : 0;
    gsap.from(el,{
        scrollTrigger:{
            trigger:el,
            start:"0% 50%",
            end:"top bottom",
            scrub:2,
        },
        xPercent:xVal, //여기에 xval변수값쓰기
        opacity:0
    })
})
데이터수치에 대한 변수 xVal을 만들어서
if문 작성 : el.dataset.x 값이 있다면(?) el.dataset.x의 값을 사용하고, 없다면(:) 0을 사용하도록 함
gsap에 xPercent에 변수를 넣어, 해당 위치에서 변수값을 사용 할 수 있도록 구성
&.one{left: -100%;}
&.two{right: 0;}서로 반대방향으로 스크롤될 수 있도록, 시작 지점을 다르게 잡아준다
텍스트를 왼쪽/오른쪽으로 고정해놔서 스크롤해도 공백이 생기지 않게
$('.sc-effect01 .effect-top.one').each(function(i,el){
  gsap.to('.sc-effect01 .effect-top.one',{
  scrollTrigger:{
  trigger:el,
  start:'top 95%',
  end:'bottom top',
  toggleClass: "hide",
  scrub:5
  },
  xPercent:50 
  })
  })
$('.sc-effect01 .effect-top.two').each(function(i,el){
  gsap.to('.sc-effect01 .effect-top.two',{
  scrollTrigger:{
  trigger:el,
  start:'top 95%',
  end:'bottom top',
  toggleClass: "hide",
  scrub:5
  },
  xPercent:-50 
  })
  })start : 내 스크롤은 맨 위에 닿고, 윈도우기준 거의 바닥(95%)에 닿을 때 시작
 .box-area{
        left: 100%;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        z-index: 1;
        width: 100%;
        display: flex;
        justify-content: center;
 }display flex, justify-content: center으로 가운데정렬하여
최대 스크롤을 해도 맨 왼쪽으로 가지 않도록 고정시킴
const effect02 = gsap.timeline({
      scrollTrigger:{
          trigger:".sc-effect02", 
          start:"0% 0%",
          end:"+=500%",
          scrub: 5,
          pin : true,
      },
    })
    effect02.addLabel('eff2')
    .to('.sc-effect02 .effect-top.one',{xPercent:50},'eff2')
    .to('.sc-effect02 .effect-top.two',{xPercent:-50},'eff2')
    .to('.box-area',{ left:'-10%'},'eff2')