-
Python(Flask)+React+SASS+mongoDB로 웹 서비스 제작하기 프로젝트(2-3) – Login Component 만들기(Animation, SASS)Node 2021. 4. 27. 19:45
진짜 진짜 진짜 하고싶었던 것 애니메이션 적용시켜서 Web-Application을 조금 더
‘트렌디’하게 보이게 하는 것… 오늘 했다 그래서 포스팅 연속으로 3개 올리고 있다.사실 paper_lee가 만든 API를 통해 회원가입 데이터 송수신 하는 것 까지 했는데 아직
완성이 안돼서 오늘 여기까지만 쓸 것..!먼저 여기 들어가보셈
http://anicollection.github.io
쩔음.내가 사용한 것은, bounceIn Left Right, bounceOut Left Right, fadeIn 이렇게 5개 씀.
먼저 여기서 코드 복사해서 ‘src/Animation.css’ 에 작성
src/Animation
/*base code*/ .animated { -webkit-animation-duration: 1s; animation-duration: 1s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .animated.infinite { -webkit-animation-iteration-count: infinite; animation-iteration-count: infinite; } .animated.hinge { -webkit-animation-duration: 2s; animation-duration: 2s; } @-webkit-keyframes bounceInLeft { 0%, 100%, 60%, 75%, 90% { -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1); transition-timing-function: cubic-bezier(0.215, .61, .355, 1) } 0% { opacity: 0; -webkit-transform: translate3d(-3000px, 0, 0); transform: translate3d(-3000px, 0, 0) } 60% { opacity: 1; -webkit-transform: translate3d(25px, 0, 0); transform: translate3d(25px, 0, 0) } 75% { -webkit-transform: translate3d(-10px, 0, 0); transform: translate3d(-10px, 0, 0) } 90% { -webkit-transform: translate3d(5px, 0, 0); transform: translate3d(5px, 0, 0) } 100% { -webkit-transform: none; transform: none } } @keyframes bounceInLeft { 0%, 100%, 60%, 75%, 90% { -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1); transition-timing-function: cubic-bezier(0.215, .61, .355, 1) } 0% { opacity: 0; -webkit-transform: translate3d(-3000px, 0, 0); -ms-transform: translate3d(-3000px, 0, 0); transform: translate3d(-3000px, 0, 0) } 60% { opacity: 1; -webkit-transform: translate3d(25px, 0, 0); -ms-transform: translate3d(25px, 0, 0); transform: translate3d(25px, 0, 0) } 75% { -webkit-transform: translate3d(-10px, 0, 0); -ms-transform: translate3d(-10px, 0, 0); transform: translate3d(-10px, 0, 0) } 90% { -webkit-transform: translate3d(5px, 0, 0); -ms-transform: translate3d(5px, 0, 0); transform: translate3d(5px, 0, 0) } 100% { -webkit-transform: none; -ms-transform: none; transform: none } } .bounceInLeft { -webkit-animation-name: bounceInLeft; animation-name: bounceInLeft } @-webkit-keyframes bounceInRight { 0%, 100%, 60%, 75%, 90% { -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1); transition-timing-function: cubic-bezier(0.215, .61, .355, 1) } 0% { opacity: 0; -webkit-transform: translate3d(3000px, 0, 0); transform: translate3d(3000px, 0, 0) } 60% { opacity: 1; -webkit-transform: translate3d(-25px, 0, 0); transform: translate3d(-25px, 0, 0) } 75% { -webkit-transform: translate3d(10px, 0, 0); transform: translate3d(10px, 0, 0) } 90% { -webkit-transform: translate3d(-5px, 0, 0); transform: translate3d(-5px, 0, 0) } 100% { -webkit-transform: none; transform: none } } @keyframes bounceInRight { 0%, 100%, 60%, 75%, 90% { -webkit-transition-timing-function: cubic-bezier(0.215, .61, .355, 1); transition-timing-function: cubic-bezier(0.215, .61, .355, 1) } 0% { opacity: 0; -webkit-transform: translate3d(3000px, 0, 0); -ms-transform: translate3d(3000px, 0, 0); transform: translate3d(3000px, 0, 0) } 60% { opacity: 1; -webkit-transform: translate3d(-25px, 0, 0); -ms-transform: translate3d(-25px, 0, 0); transform: translate3d(-25px, 0, 0) } 75% { -webkit-transform: translate3d(10px, 0, 0); -ms-transform: translate3d(10px, 0, 0); transform: translate3d(10px, 0, 0) } 90% { -webkit-transform: translate3d(-5px, 0, 0); -ms-transform: translate3d(-5px, 0, 0); transform: translate3d(-5px, 0, 0) } 100% { -webkit-transform: none; -ms-transform: none; transform: none } } .bounceInRight { -webkit-animation-name: bounceInRight; animation-name: bounceInRight } @-webkit-keyframes bounceOutLeft { 20% { opacity: 1; -webkit-transform: translate3d(20px, 0, 0); transform: translate3d(20px, 0, 0) } 100% { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0) } } @keyframes bounceOutLeft { 20% { opacity: 1; -webkit-transform: translate3d(20px, 0, 0); -ms-transform: translate3d(20px, 0, 0); transform: translate3d(20px, 0, 0) } 100% { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); -ms-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0) } } .bounceOutLeft { -webkit-animation-name: bounceOutLeft; animation-name: bounceOutLeft } @-webkit-keyframes bounceOutRight { 20% { opacity: 1; -webkit-transform: translate3d(-20px, 0, 0); transform: translate3d(-20px, 0, 0) } 100% { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0) } } @keyframes bounceOutRight { 20% { opacity: 1; -webkit-transform: translate3d(-20px, 0, 0); -ms-transform: translate3d(-20px, 0, 0); transform: translate3d(-20px, 0, 0) } 100% { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); -ms-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0) } } .bounceOutRight { -webkit-animation-name: bounceOutRight; animation-name: bounceOutRight } /*the animation definition*/ @-webkit-keyframes fadeIn { 0% { opacity: 0 } 100% { opacity: 1 } } @keyframes fadeIn { 0% { opacity: 0 } 100% { opacity: 1 } } .fadeIn { -webkit-animation-name: fadeIn; animation-name: fadeIn }
사이트 들어가기 귀찮으면 이거 복붙하면 됨!
pages/Main.js 수정
import React, { Component } from 'react'; import Join from 'components/Join'; import Login from 'components/Login'; import '../Animation.css' import queryString from "query-string"; import 'style/Main.scss'; import leftImg from '/home/linesys/OLLOC/src/img/main.png' class Main extends Component { state = { direction: 'animated fadeIn' } loginsplit = (query) => { if(query === 'login') return false; else return true; } move = (getDirection) => { // 자식 컴포넌트에서 값을 가져옴 this.setState({ direction: getDirection, }) } render() { const {location} = this.props; const query = queryString.parse(location.search); const detail = this.loginsplit(query.detail); return ( <div id = "main"> <img className = "animated fadeIn" src={leftImg} alt="이미지"/> // 이미지도 초기 로드시 fadeIn효과로 불러지게 함 { detail ? <Join animation={this.move} direction={this.state.direction} /> : <Login animation={this.move} direction={this.state.direction} /> } </div> ); }; } export default Main;
사용법은 간단하게 class명에 animated와 ‘적용시킬 애니메이션 이름’을 추가해주면 된다.
페이지 새로고침을 했을 때 이전에 애니메이션이 중복되서 나오는 것을 방지하기 위해
direction을 fadeIn으로 초기화 시켰다.
join, login 서로 컴포넌트가 전환될 때 어떤 애니메이션을 불러올지 통신을 위해 animation, direction props를 전달해준다.components/Join.js 수정
import React, {Component} from "react"; import "../Animation.css" import { Redirect } from 'react-router-dom'; class Join extends Component{ changeView = () => { this.setState({ animation: 'animated bounceOutLeft' }); this.props.animation('animated bounceInRight'); setTimeout(()=>{ this.setState({ redirect: true }) }, 300); } constructor(props){ super(props); this.state ={ animation: this.props.direction, redirect: false, } } render(){ if(this.state.redirect){ return <Redirect push to ='main/?detail=login' />; } return( <div id ="join"> <form id="loginForm" className={this.state.animation}> <h1>OLLoc</h1> <span className="loginText">친구들의 지도에 그려진 사진과 글을 보려면 가입하세요</span> <button className="mainBtn">facebook으로 로그인</button> <div id="line">또는</div> <input className="textInput" placeholder="휴대폰 번호 또는 이메일 주소" /> <input className="textInput" placeholder="성명" /> <input className="textInput" placeholder="사용자 이름" /> <input className="textInput" placeholder="비밀번호" /> <button className="mainBtn">가입</button> <span className="loginText">가입하면 OLLoc의 약관, 데이터 정책 및 쿠키 정책에 동의하게 됩니다.</span> </form> <div id="checkMem" className={this.state.animation}> 계정이 있으신가요? <span id = "loginBtn" onClick={this.changeView} >로그인</span> </div> </div> ); } } export default Join;
부모에게 받은 props.direction으로 state.animation을 초기화한다.
#loginForm -> div안에있는 form 태그에 state.animation을 className으로 정해줘
애니메이션 효과를 준다.
이렇게 하면 초기 로드시 fadeIn 효과를 줄 수 있다.
이어서 하단의 ‘<span id = “loginBtn” onClick={this.changeView} >로그인</span>’ 을 클릭하면 changeView라는 함수를 통하게 된다.먼저 현재 state.animation을 bounceOutLeft로 변경하여 re-rendering 되며 왼쪽으로 사라지는 애니메이션을 주게된다.
그리고 부모 컴포넌트로부터 받은 props.animation 함수를 통해 매개변수로 bounceInRight를 줬다. 이렇게 하면 부모가 Join.js의 형제(?)인 Login.js에게 bounceInRight를 줄 것이고 Login Component가 오른쪽에서부터 왼쪽으로 나타나는 애니메이션을 주며 뷰가 전환될 것이다. (새로고침 없이! react-router!)
그리고 이어서 setTimeout이 있다 사실 componentWillUnmount 메소드를 통해
애니메이션을 주려 했으나 저기에서 state를 변경해도 새로운 DOM이 나타나 버려서
애니메이션이 진행될 시간인 300ms의 딜레이 후 /main/?detail=login로 리다이렉트 하게 했다.state.redirect가 true가 되며 render(){if(this.state.redirect)}를 통해 리다이렉팅 되게 된다.
components/Login.js수정
import React, {Component} from 'react'; import { Redirect, Link } from 'react-router-dom'; class Login extends Component{ changeView = () => { this.setState({ animation: 'animated bounceOutRight' }); this.props.animation('animated bounceInLeft'); setTimeout(()=>{ this.setState({ redirect: true }) }, 300); } constructor(props){ super(props); this.state ={ animation: this.props.direction, redirect: false, } } render(){ if(this.state.redirect){ return <Redirect push to ='/main' />; } return( <div id ="login"> <form className={this.state.animation} id="loginForm"> <span id="prevBtn" onClick={this.changeView}><i className="fas fa-arrow-left"></i></span> <h1 id="mainTitle">OLLoc</h1> <span className="loginText">친구들의 지도에 그려진 사진과 글을 보려면 가입하세요</span> <button className="mainBtn">facebook으로 로그인</button> <div id="line">또는</div> <input className="textInput" placeholder="휴대폰 번호 또는 이메일 주소" /> <input className="textInput" placeholder="비밀번호" /> <Link to ="/" className="noUnderLine" ><button className="mainBtn">로그인</button></Link> <span className="loginText">가입하면 OLLoc의 약관, 데이터 정책 및 쿠키 정책에 동의하게 됩니다.</span> </form> </div> ); } } export default Login;
‘components/Join.js’ 와 같은 원리로 작동한다.
스타일을 주자! ‘style/Main.scss’ 작성
sass는 기존 css에 변수와 조건문, 반복문 등 기존의 css를 확장시켜 좀 더 편리하게
해주는 스타일시트 언어다.
사용하기 위해서는 ‘node-sass’라는 라이브러리가 필요하다. 웹브라우져가 기존의 css코드로 이해할 수 있도록 컴파일 해주는 역할을 한다.$ yarn add node-sass
이제 코드를 작성하자.
#join, #login{ overflow: hidden; display: inline-block; width: 400px;}
다만 위 코드만 설명하면 상단에 이 부분은 애니메이션이 bounceIn&Out될 때
양쪽 끝에서 움직이기
때문에 제한을 걸기 위해 overflow:hidden, display: inline-block; width: 400px로
크기를 정해주고 내부 요소들이 부모 요소 밖으로 넘치는 경우를 예방했다.결과
홈으로 접속하여 회원가입 화면으로 전환될 때 fadeIn 효과
로그인 버튼 누르고 이전 버튼을 눌렀을 때 bounceIn&Out 효과
그리고 다시 새로고침을 했을 때 fadeIn 효과가 나오는 것을 확인할 수 있다.'Node' 카테고리의 다른 글