인텔리제이 프론트엔드 기술

08_Pilot_Project  -  01_Blog  -  00_JSLIB 폴더 만들기

 

명령프롬포트 실행 (cmd 입력)

명령 프롬포트에 npx create-react-app frontend-typescript --template typescript 입력

(성공 화면)

src 하위에
assets components pages 폴더 만들고
assets 하위에
css images img 폴더 만들고

css.zip
0.00MB
images.zip
0.55MB
img.zip
14.80MB

 

위에 파일 넣기

 

 

components 하위폴더로
common 만들고


HeaderCom.tsx 생성

// HeaderCom.tsx : rfce
import React from "react";
import { Link } from "react-router-dom";

function headerCom() {
  return (
    <nav className="navbar navbar-expand-lg navbar-dark bg-primary" >
      <div className="container-fluid">
        <a className="navbar-brand" href="/">
          Simple Coding
        </a>
        <button
          className="navbar-toggler"
          type="button"
          data-bs-toggle="collapse"
          data-bs-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span className="navbar-toggler-icon"></span>
        </button>
        <div className="collapse navbar-collapse" id="navbarSupportedContent">
          <ul className="navbar-nav me-auto mb-2 mb-lg-0">
            <li className="nav-item">
              <a className="nav-link active" aria-current="page" href="/">
                Home
              </a>
            </li>
            {/* Simple 메뉴 시작 */}
            <li className="nav-item dropdown">
              <a
                className="nav-link active dropdown-toggle"
                href="#"
                role="button"
                data-bs-toggle="dropdown"
                aria-expanded="false"
              >
                Simple
              </a>
              <ul className="dropdown-menu">
                <li>
                  <Link to={"/bootstrap-icons"} className="dropdown-item">
                    Bootstrap-icons
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/countup"} className="dropdown-item">
                    CountUp
                  </Link>
                </li>
                <li>
                  <Link to={"/countup-exam"} className="dropdown-item">
                    CountUp-Exam
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/typed"} className="dropdown-item">
                    Typed
                  </Link>
                </li>
                <li>
                  <Link to={"/typed-exam"} className="dropdown-item">
                    Typed-Exam
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/wow"} className="dropdown-item">
                    Wow
                  </Link>
                </li>
                <li>
                  <Link to={"/wow-exam"} className="dropdown-item">
                    Wow-Exam
                  </Link>
                </li>
              </ul>
            </li>
            {/* Simple 메뉴 끝 */}

            {/* Complex 메뉴 시작 */}
            <li className="nav-item dropdown">
              <a
                className="nav-link active dropdown-toggle"
                href="#"
                role="button"
                data-bs-toggle="dropdown"
                aria-expanded="false"
              >
                Complex
              </a>
              <ul className="dropdown-menu">
                <li>
                  <Link to={"/simple-lightbox"} className="dropdown-item">
                    Simple-lightbox
                  </Link>
                </li>
                <li>
                  <Link to={"/simple-lightbox-exam"} className="dropdown-item">
                    Simple-lightbox-exam
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/owl-carousel"} className="dropdown-item">
                    Carousel
                  </Link>
                </li>
                <li>
                  <Link to={"/owl-carousel-exam"} className="dropdown-item">
                    Carousel-Exam
                  </Link>
                </li>
                <li>
                  <Link to={"/owl-carousel-wow-exam"} className="dropdown-item">
                    Carousel-Wow-Exam
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/isotope"} className="dropdown-item">
                    Isotope
                  </Link>
                </li>
                <li>
                  <Link to={"/isotope-exam"} className="dropdown-item">
                    Isotope-Exam
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/easing"} className="dropdown-item">
                    Easing
                  </Link>
                </li>
                <li>
                  <hr className="dropdown-divider" />
                </li>
                <li>
                  <Link to={"/datepicker"} className="dropdown-item">datepicker Calendar</Link>
                </li>
                <li>
                  <Link to={"/daterange-picker"} className="dropdown-item">
                    daterange-picker Calendar
                  </Link>
                </li>
              </ul>
            </li>
            {/* Complex 메뉴 끝 */}
          </ul>
        </div>
      </div>
    </nav>
  );
}

export default headerCom;

 

App.tsx 수정

import React from 'react';
import logo from './logo.svg';
import './App.css';
import HeaderCom from './components/common/HeaderCom';

function App() {
  return (
    <div className="App">
      {/* 머리말 */}
      <HeaderCom/>

      {/* 본문 */}
    </div>
  );
}

export default App;


통합터미널 열고
npm i react-router-dom

 

index.tsx 수정 (BrowserRouter 수정)

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 1) 메뉴 lib import
import { BrowserRouter } from 'react-router-dom';



const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <BrowserRouter>
  <App/>
  </BrowserRouter>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

index.html 수정
title 밑에 부트스트랩 링크
/body 위에 
body : 부트스트랩 & jquery cdn

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>

    <!-- 부트스트랩 css link -->
    <link
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  </body>
</html>

실행 결과

부트스트랩 수정하여 색변경 가능

 

이번엔 여러가지 프론트엔드 기능들을 배워보려한다

순서는 기본적으로 pages 폴더에 (기능명).tsx 을 생성하고 

app.tsx 에서 라우트를 통해 사이트와 연결 하는 것이다 추가 작업이 필요한 기능있다면 따로 기재하겠다

 

시작 전 

Read.me를 따라 npm을 설치하고 시작

Read.md

# 메뉴 라이브러리 
npm i react-router-dom

# 0) jquery
npm i --save-dev @types/jquery
npm i @types/jqueryui

# 0) bootstrap
npm install --save @types/bootstrap

# 1) countup lib : 숫자 올라가기 외부 lib
# 공홈 : 
https://github.com/bfintal/Counter-Up
#    (cdn(링크), npm(설치))
# waypoints 필수 설치 필요
# 1-1) <!-- 1) counterup :  -->
# <script src="/lib/counterup/counterup.min.js"></script>
# <!-- 1-1) counterup + waypoints  -->
# <script src="/lib/waypoints/waypoints.min.js"></script>

# 2) typed.js : 화면에 타자처럼 타이핑 애니메이션 효과를 주는 lib
# => npm 설치 (cdn 있음)
# 공홈 : 
https://mattboldt.github.io/typed.js/
npm install typed.js
# 2-1) typed.js import 방법 (MIT 라이선스)
import Typed from "typed.js";

# 3) wowjs : GNU GPL 라이선스 v3(제약: 소스 공개 필요)
# 공홈 : 
https://wowjs.uk/
# 유사라이브러리 : AOS lib (MIT 라이선스)
npm i wowjs

# 3-1) wowjs import 방법
import { WOW } from "wowjs";
# 3-2) animate.css import : App.tsx
# // todo: animate css import (wow 사용시 import 필요) : App.tsx 
import "wowjs/css/libs/animate.css";

# 4) 라이트박스 lib : SimpleLightbox 설치
# (cdn, npm(설치))
# 공홈 : 
https://simplelightbox.com/
npm install simplelightbox
# 4-1) import SimpleLightbox from "simplelightbox" 설치 : initMain.js
import SimpleLightbox from "simplelightbox";
# 4-2) // todo: simplelightbox css import : App.tsx
import "simplelightbox/dist/simple-lightbox.css";

# 5) owl-carousel lib 
# 회전목마 : 여러개의 사진이 자동으로 돌아가게 하는 lib
# 유사 lib : swiper
# (cdn(index.html 링크), npm(설치))
# 공홈 : 
https://owlcarousel2.github.io/OwlCarousel2/
# 5-1) index.html : css link
# <link href="/lib/owlcarousel/assets/owl.carousel.css" rel="stylesheet" />
# 5-2) index.html : js link (body)
# <script src="/lib/owlcarousel/owl.carousel.min.js"></script>
# 5-3) type 설치
npm i @types/owl.carousel

# 6) isotope 설치 : (공홈: 
https://isotope.metafizzy.co/)
# 이미지들의 정렬을 해주는 lib
# (참고) npm install isotope-layout --save
# npm i @types/isotope-layout
# (참고) npm i imagesloaded
# npm i @types/imagesloaded
# cdn 설치 : index.html js 링크 걸기
# <!-- 5) isotope : 
https://isotope.metafizzy.co/
 -->
# <script src="/lib/isotope/isotope.pkgd.min.js"></script>
# <!-- 5-1) isotope 이미지 겹침 문제로 사용 -->
# <script src="
https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.js
"></script>

# 7) easing 라이브러리 
# (cdn(진행), npm) : index.html 
# 공홈 : 
https://gsgd.co.uk/sandbox/jquery/easing/
# 예) 처음(천천히) -> 중간(빨리) -> 끝(천천히) : 시간의 흐름(애니메이션)
# 예) 처음(빨리) -> 중간(빨리) -> 끝(천천히)   : 시간의 흐름(애니메이션)
# <script src="/lib/easing/easing.min.js"></script>

# 8) 달력 : 
# 8-1) jquery-ui 달력 : (cdn 진행) index.html 
# 공홈 : 
https://jqueryui.com/datepicker/
# css 링크
# <link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
# js 링크
# <script src="
https://code.jquery.com/ui/1.13.2/jquery-ui.js
"></script>

# 8-2) range calendar 달력 : (cdn 진행) index.html 
# 공홈 : 
https://www.daterangepicker.com/
# css link
# <link rel="stylesheet" href="css/daterangepicker.css" />
# js link
# <script src="js/moment.min.js"></script>
# <script src="js/daterangepicker.js"></script>


# 공통) 외부 lib 타입 없을때 대처하는 방법
# 1) tsconfig.json 파일 - compilerOptions 속성에 아래 추가 : 프로젝트시작위치/types - 이 위치에 타입을 인식하게 하는 경로 설정
"typeRoots": ["./types", "./node_modules/@types"], // 보통 types 폴더를 만들어 타입 정의
# 2) types/외부라이브러리명/index.d.ts 파일 생성 후 아래 추가
declare module '외부라이브러리명';

 

순서

BootstrapIcons - CounterUp - TypedCom - WowCom

SimpleLightboxCom - OwlCarouselCom - IsotopeCom - EasingCom - Datepicker - DaterangePicker

 

App.tsx (완성본)

각 페이지 만들고 하나씩 추가

// todo: external lib import
// todo: animate css import (wow 사용시 import 필요)
import "wowjs/css/libs/animate.css";
// todo: simplelightbox css import
import "simplelightbox/dist/simple-lightbox.css";

// todo: internal import
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import HeaderCom from "./components/common/HeaderCom";
import { Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import BootstrapIcons from "./pages/BootstrapIcons";
import CounterUp from "./pages/CounterUp";
import CounterUpExam from "./pages/CounterUpExam";
import TypedCom from "./pages/TypedCom";
import TypedComExam from "./pages/TypedComExam";
import WowCom from "./pages/WowCom";
import SimpleLightboxCom from "./pages/SimpleLightboxCom";
import SimpleLightboxComExam from "./pages/SimpleLightboxComExam";
import OwlCarouselCom from "./pages/OwlCarouselCom";
import OwlCarouselComExam from "./pages/OwlCarouselComExam";
import IsotopeCom from "./pages/IsotopeCom";
import IsotopeComExam from "./pages/IsotopeComExam";
import EasingCom from "./pages/EasingCom";
import Datepicker from "./pages/Datepicker";
import DaterangePicker from "./pages/DaterangePicker";

function App() {
  return (
    <div className="App">
      {/* 머리말 */}
      <HeaderCom />

      {/* 본문 */}
      <div className="container mt-3">
        <Routes>
          {/* / : 홈메뉴(1st 페이지) */}
          <Route path="/" element={<Home />} />
          <Route path="/bootstrap-icons" element={<BootstrapIcons />} />

          {/* countUp */}
          <Route path="/countup" element={<CounterUp />} />
          {/* 연습1) 1,234,567.00 줄바꿈, 1.99 줄바꿈, 12345 줄바꿈 화면 카운팅하세요 */}
          <Route path="/countup-exam" element={<CounterUpExam />} />

          {/* typed.js */}
          <Route path="/typed" element={<TypedCom />} />
          {/* 연습2) ["안녕하세요", "또 만납시다.", "잘가세요."]
              <!-- backSpeed: 0, typeSpeed: 0 으로 사용해 보세요 -->
           */}
          <Route path="/typed-exam" element={<TypedComExam />} />

          {/* wowjs */}
          <Route path="/wow" element={<WowCom />} />

          {/* simplelightbox */}
          <Route path="/simple-lightbox" element={<SimpleLightboxCom />} />
          {/* div(gallery) */}
          {/* 연습3)  "../assets/img/gallery/full/01.jpg" ~ 06.jpg: 풀이미지 (화면이미지) a태그
                      "../assets/img/gallery/thumb/01.jpg" ~ 06.jpg : 작은이미지 (클릭시 나오는 이미지) img 태그

          */}
          <Route
            path="/simple-lightbox-exam"
            element={<SimpleLightboxComExam />}
          />

          {/* owl-carousel */}
          <Route path="/owl-carousel" element={<OwlCarouselCom />} />
          {/* 연습 4) 주어진 html 이용해서 캐러셀을 구현하세요 */}
          <Route path="/owl-carousel-exam" element={<OwlCarouselComExam />} />

          {/* isotope(동위원소)*/}
          <Route path="/isotope" element={<IsotopeCom />} />
          {/* 연습 5)
              first, second, third 로 div 태그를 지정하고 isotope 기능을 추가하세요
           */}
          <Route path="/isotope-exam" element={<IsotopeComExam />} />

          {/* easing */}
          <Route path="/easing" element={<EasingCom />} />

          {/* calendar */}
          <Route path="/datepicker" element={<Datepicker />} />
          <Route path="/daterange-picker" element={<DaterangePicker />} />
        </Routes>
      </div>
    </div>
  );
}

export default App;

 

BootstrapIcons 

index.html

bootstrap css link 밑에

Bootstrap Icons 넣기

 

pages

BootstrapIcons.tsx 생성

// BootstrapIcons.tsx : rfce
// 컴포넌트 이름 : 첫글자 대문자로 만들기(안만들면 에러발생)
import React from "react";

function BootstrapIcons() {
  return (
    <div>
      {/* 공홈 : https://icons.getbootstrap.com/ */}
      {/* 1) Bootstrap Icons : 홈페이지 각각의 아이콘 모양을 쉽게 제공 */}
      {/* 사용법(install): 부트스트랩-아이콘 cdn 걸기 : index.html */}
      {/*     <i className='bi bi-아이콘 클래스명'>글자</i> */}
      {/* 유사사이트(참고): font-awesome 사이트 */}
      <i className="bi bi-heart-fill"> : bi-heart-fill</i><br />
      <i className="bi bi-heart"> : bi-heart</i><br />
      <i className="bi bi-gem"> : bi-gem </i><br />
      <i className="bi bi-laptop"> : bi-laptop </i><br />
      <i className="bi bi-globe"> : bi-globe </i><br />
      <i className="bi bi-person-standing-dress"> : bi-person-standing-dress </i><br />
      <i className="bi bi-person-wheelchair"> : bi-person-wheelchair </i><br />
    </div>
  );
}

export default BootstrapIcons;

 

결과

CounterUp 

밑에 파일 다운받아서 압축풀고

counterup.zip
0.00MB

 

public 하위에

lib 폴더 만들고

lib 하위에

counterup 폴더만들고

counterup.min.js 파일 복사

 

 

waypoints.zip
0.00MB

 

lib 하위에

waypoints 폴더 만들고

파일 복사

 

pages

CounterUp.tsx 생성

// CounterUp.tsx : rfce
import React, { useEffect } from "react";
import initMain from "../assets/js/initMain";

function CounterUp() {
    // 화면이 뜰때 실행되는 이벤트 :
    useEffect(()=>{
        // 실행문
        initMain();
    },[]);

  return (
    <div>
        {/* 사용법 :
            => html 부분
                <태그 data-toggle="변수명">
                    숫자
                </태그>
            => js 부분
                ($(선택자) as any).counterUp({
                    delay: 숫자, // 지연시간(1/1000초)
                    time: 숫자   // 화면표시가 끝나는 시간(1/1000초)
                })
         */}
      <h2 className="text-primary fw-bold mb-0" data-toggle="counter-up">
        20000
      </h2>
    </div>
  );
}

export default CounterUp;

 

assets 하위에

js폴더 만들기

js폴더에 initMain.ts 만들기

initMain.ts 수정 [data-toggle="counter-up"]

 

initMain.ts(최종본이라 모든 기능 다 들어가있음)

// initMain.ts
// todo: typed.js import
import Typed from "typed.js";
// todo: wowjs import
import { WOW } from "wowjs";
// todo: simplelightbox import
import SimpleLightbox from "simplelightbox";

export default function initMain() {
    // todo: 1) countup lib 사용
    // todo: 사용법 : $(선택자).counterUp({옵션설정});
    // todo: jquery 타입 무시 : ($(선택자) as any)
    ($('[data-toggle="counter-up"]') as any).counterUp({
        delay: 10,
        time: 2000
    });

    // todo: 1-1) 연습 counterup lib
    // 연습1) 1,234,567.00 줄바꿈, 1.99 줄바꿈, 12345 줄바꿈 화면 카운팅하세요
    ($('.counter') as any).counterUp({
        delay: 10,
        time: 2000
    });

    // todo: 2)  typed.js lib
    // 사용법 :
    //     => html : <span id="변수명"></span>
    //     => js : new Typed(#변수명, {옵션})

    let typed1 = document.querySelector("#typed1");

    // typed1 있으면 타이핑 객체 생성
    if(typed1 != null) {
        new Typed("#typed1", {
            // 타이핑 대상 글자 : strings: ["화면표시1",...,"화면표시n"]
            strings: ["원하는 글씨를", "순서대로", "출력해 줍니다."],
            typeSpeed: 100, // 타이핑 되는 속도
            backSpeed: 100, // 지워지는 속도
            cursorChar: "_",
            loop: true,     // 글자 순환          
        })
    }

    // todo: 2-1) 연습  typed.js lib
    // ["안녕하세요", "또 만납시다.", "잘가세요."]
    // <!-- backSpeed: 0, typeSpeed: 0 으로 사용해 보세요
    let typedExam = document.querySelector("#typedExam");

    // typedExam 있으면 타이핑 객체 생성
    if(typedExam != null) {
        new Typed("#typedExam", {
            // 타이핑 대상 글자 : strings: ["화면표시1",...,"화면표시n"]
            strings: ["안녕하세요", "또 만납시다.", "잘가세요."],
            typeSpeed: 0, // 타이핑 되는 속도
            backSpeed: 0, // 지워지는 속도
            cursorChar: "_",
            loop: true,     // 글자 순환          
        })
    }

    // todo: 3) wowjs
    // 사용법 : new WOW().init()
    new WOW().init();

    // todo: 4) SimpleLightbox
    new SimpleLightbox(".portfolio a");
   
    // todo: 4-1) 연습 SimpleLightbox
    new SimpleLightbox(".gallery a");

    // todo: 5) owl-carousel
    // 사용법 : $(선택자).owlCarousel({옵션});
    ($(".carousel-div") as any).owlCarousel({
        // 옵션
        autoplay: true,
        smartSpeed: 1000,
        nav: true,
        items: 1,
        loop: true
    });

   
    // todo: 5-1) 연습 owl-carousel  
    // 사용법 : $(선택자).owlCarousel({옵션});
    ($(".carousel-div-exam") as any).owlCarousel({
        // 옵션
        autoplay: true,
        smartSpeed: 1000,
        nav: true,
        items: 2,      // 화면에 보여줄 이미지 개수
        loop: true
    });

    // todo: 6) isotope + imageLoaded(버그 해결)
    // 버그 : 이미지 겹치는 버그
    // 소제목 부분 :
    // 필터 부분   : portfolio-container 클래스
    // 사용법 : ($("필터선택자") as any).imagesLoaded(function () {
//                 isotope 필터 설정 코딩
//                 let 변수명 = $(필터선택자).isotope({
//                     itemSelector: "필터선택자의 자식선택자(div여러개)",(**)
//                     layoutMode: "화면모드"
//                  })
//                 isotope 소제목 설정 코딩
//                
    //          }
    ($(".portfolio-container") as any).imagesLoaded(function () {
        // 필터 선택자 : portfolio-container 태그를 선택해서 isotope 객체 생성
        let portfolioIsotope = ($(".portfolio-container") as any).isotope({
          itemSelector: ".portfolio-item",
          layoutMode: "fitRows",
        });
   
        // 소제목 선택자 : #portfolio-flters li
        // 소제목을 클릭했을때 실행됨
        $("#portfolio-flters li").on("click", function () {
          $("#portfolio-flters li").removeClass("active"); // active 클래스 제거
          $(this).addClass("active"); // 현재 클릭한 소제목에 active 클래스 추가
   
          // data-filter=값 , 값 : *(필터명), .first(필터명), .second(필터명)
          // 현재 클릭한 필터의 값을 선택해서 isotope 를 적용함
        //   isotope 객체 생성 : $(필터선택자).isotope({
        //        filter: 필터명
        //   });
        //  $(this).data("filter") => data-filter="값" 을 가져오는 함수
          portfolioIsotope.isotope({ filter: $(this).data("filter") });
        });
      });
 
     
    // todo: 6-1) 연습 isotope + imageLoaded(버그 해결)
    ($(".exam-container") as any).imagesLoaded(function () {
        // 필터 선택자 : portfolio-container 태그를 선택해서 isotope 객체 생성
        let portfolioIsotope = ($(".exam-container") as any).isotope({
          itemSelector: ".exam-item",
          layoutMode: "fitRows",
        });
   
        // 소제목 선택자 : #portfolio-flters li
        // 소제목을 클릭했을때 실행됨
        $("#exam-flters li").on("click", function () {
          $("#exam-flters li").removeClass("active"); // active 클래스 제거
          $(this).addClass("active"); // 현재 클릭한 소제목에 active 클래스 추가
   
          // data-filter=값 , 값 : *(필터명), .first(필터명), .second(필터명)
          // 현재 클릭한 필터의 값을 선택해서 isotope 를 적용함
        //   isotope 객체 생성 : $(필터선택자).isotope({
        //        filter: 필터명
        //   });
        //  $(this).data("filter") => data-filter="값" 을 가져오는 함수
          portfolioIsotope.isotope({ filter: $(this).data("filter") });
        });
      });

      // todo: 7) easing
      $(function () {
        // boxing 클릭하면 애니메이션 실행
        $("#boxing").click(function () {
          $("#boxing")
          // .animate({css속성:값}, 지속시간, easing_효과)
          // easeOutElastic 함수 : easing.js 에 라이브러리 함수가 정의되어 있음
            .animate({ marginLeft: "50px" }, 1000, "easeOutElastic")
            .animate({ marginTop: "50px" }, 1000, "easeOutBounce")
            .animate({ marginLeft: "-150px" }, 1000, "easeOutQuad")
            .animate({ marginTop: "-150px" }, 1000, "easeInOutBack")
            .animate(
              { height: "100px", marginTop: "0px", width: "50px" },
              1000,
              "easeOutElastic"
            )
            .animate(
              { height: "50px", marginTop: "25px", width: "50px" },
              1000,
              "easeOutBounce"
            )
            .animate(
              { height: "50px", marginTop: "25px", width: "100px" },
              1000,
              "easeOutQuad"
            )
            .animate(
              { height: "100px", marginTop: "0px", width: "100px" },
              1000,
              "easeInOutBack"
            );
        });
      });

}

 

결과 (정해놓은 숫자까지 정해놓은 속도로 올라감)

TypedCom.tsx

 

pages

TypedCom.tsx 생성

// TypedCom.tsx : rfce
import React, { useEffect } from 'react'
import initMain from '../assets/js/initMain';

function TypedCom() {

    useEffect(()=>{
        // 여기
        initMain();
    },[]);

  return (
    <div>
        <span id="typed1"></span>
    </div>
  )
}

export default TypedCom

 

initMain 수정 (typed 생성)

 

결과 (글자 계속 변경)

WowCom.tsx

 

pages

WowCom.tsx 생성

// WowCom.tsx : rfce
import React, { useEffect } from "react";
import initMain from "../assets/js/initMain";

function WowCom() {

  useEffect(()=>{
    // 여기
    initMain();
  },[]);

  return (
    // 여기
    <div className="container-xxl py-6" id="about">
      <div className="container">
        <div className="row g-5">
          {/* 1st wow 시작 */}
          {/* 사용법 : wow bounceInUp data-wow-delay="0.1s" */}
          {/*   => html :  
            <div className="wow 애니메이션상수" data-wow-delay="지연시간s">
              대상태그
            </div>
           */}
          {/*   => js   :  
            new WOW().init();
          */}
          <div className="col-lg-3 wow bounceInUp" data-wow-delay="0.1s">
            <p className="mb-4">
              맛보기 강의자료와 유/무료 강의자료로 어려운 IT 기술을 쉽게 취득할
              수 있도록 도움을 드립니다.
            </p>
          </div>
          {/* 1st wow 끝 */}

          {/* 2nd wow 시작 */}
          {/* 사용법 : wow slideInLeft data-wow-delay="0.1s" */}
          <div className="col-lg-3 wow slideInLeft" data-wow-delay="0.5s">
            <p className="mb-4">
              이 때까지 온라인 강의 및 피드백을 들은 고객들에게 진심으로
              감사드립니다.
            </p>
          </div>
          {/* 2nd wow 끝 */}

          {/* 3rd wow 시작 */}
          {/* 사용법 : wow fadeInUp data-wow-delay="0.1s" */}
          <div className="col-lg-3 wow fadeInUp" data-wow-delay="0.5s">
            <p className="mb-4">
              이 때까지 온라인 강의 및 피드백을 들은 고객들에게 진심으로
              감사드립니다.
            </p>
          </div>
          {/* 3rd wow 끝 */}

          {/* 4th wow 시작 */}
          {/* 사용법 : wow flipInX data-wow-delay="0.1s" */}
          <div className="col-lg-3 wow flipInX" data-wow-delay="0.5s">
            <p className="mb-4">
              이 때까지 온라인 강의 및 피드백을 들은 고객들에게 진심으로
              감사드립니다.
            </p>
          </div>
          {/* 4th wow 끝 */}
        </div>
      </div>
    </div>
  );
}

export default WowCom;

 

initMainimport { WOW } from "wowjs"; 추가

app.tsx

import "wowjs/css/libs/animate.css"; 추가

 

public 하위에

types 폴더 만들고

하위에 wowjs 폴더만들고

index.d.ts 생성

 

index.d.ts 

declare module 'wowjs';

 

tsconfig.json 파일 수정 (최종본)

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "typeRoots": ["./types", "./node_modules/@types"], // 보통 types 폴더를 만들어 타입 정의
  },
  "include": [
    "src"
  ]
}

 

결과

SimpleLightboxCom

app.tsx에 추가 - import "simplelightbox/dist/simple-lightbox.css";

 

initMain.ts 에 추가 -import SimpleLightbox from "simplelightbox";

 

SimpleLightboxCom.tsx 생성

// SimpleLightboxCom.tsx : rfce
import React, { useEffect } from 'react'
import initMain from '../assets/js/initMain';

// 이미지 경로 import
import img01 from "../assets/img/portfolio/fullsize/1.jpg";
import img02 from "../assets/img/portfolio/fullsize/2.jpg";
import img03 from "../assets/img/portfolio/fullsize/3.jpg";
import img04 from "../assets/img/portfolio/fullsize/4.jpg";
import img05 from "../assets/img/portfolio/fullsize/5.jpg";
import img06 from "../assets/img/portfolio/fullsize/6.jpg";

import imgt01 from "../assets/img/portfolio/thumbnails/1.jpg";
import imgt02 from "../assets/img/portfolio/thumbnails/2.jpg";
import imgt03 from "../assets/img/portfolio/thumbnails/3.jpg";
import imgt04 from "../assets/img/portfolio/thumbnails/4.jpg";
import imgt05 from "../assets/img/portfolio/thumbnails/5.jpg";
import imgt06 from "../assets/img/portfolio/thumbnails/6.jpg";


function SimpleLightboxCom() {

    useEffect(()=>{
        initMain();
    },[]);

  return (
    // 여기
    <div>
      <h1 className="align-center">Simple Lightbox Demo Page</h1>
      {/* 사용법 :
            => html :
                <div className="부모선택자명">
                    <a href={이미지경로1}>
                        <img src={이미지경로1} />
                    </a>
                    ...
                    <a href={이미지경로n>
                        <img src={이미지경로n} />
                    </a>
                </div>
            => js :
                new SimpleLightbox("부모선택자 자식선택자(a태그)")
       */}
      <div className="row portfolio">
        <a href={img01} className="col-4 ">
          <img src={imgt01} />
        </a>
        <a href={img02} className="col-4 ">
          <img src={imgt02} />
        </a>
        <a href={img03} className="col-4 ">
          <img src={imgt03} />
        </a>
        <a href={img04} className="col-4 ">
          <img src={imgt04} />
        </a>
        <a href={img05} className="col-4 ">
          <img src={imgt05} />
        </a>
        <a href={img06} className="col-4 ">
          <img src={imgt06} />
        </a>
        <div className="clear"></div>
      </div>
    </div>    
  )
}

export default SimpleLightboxCom

 

types 하위에 simplelightbox 폴더 생성

index.d.ts생성

declare module 'simplelightbox';

 

결과

OwlCarouselCom 

owlcarousel.zip
0.04MB

 

public - lib - owlcarousel폴더 만들고 파일 넣기

index.htmlcss 링크(헤드)js 링크(바디)에 수정

 

index.html 수정

 

pages에

OwlCarouselComExam.tsx 생성

// OwlCarouselCom.tsx : rfce
import React, { useEffect } from "react";
import initMain from "../assets/js/initMain";
// 내가 만든 css
import "../assets/css/OwlCarouselCom.css";

function OwlCarouselCom() {

  useEffect(()=>{
    initMain();
  },[])

  return (
    <div>
      {/* 사용법 :
          => html : 컨텐츠1 ~ 컨텐츠n 돌아감
            <div className="owl-carousel owl-theme 클래스명">
              <div> 컨텐츠1 </div>
              ...
              <div> 컨텐츠n </div>
            </div>
          => js :
            $(클래스명).owlCarousel({
              autoplay: true,   // 자동으로 이미지가 돌아가는 설정
              smartSpeed: 1000, // 이미지가 변경될때 변경 속도
              nav: true,        // 메뉴 버튼
              items: 1,         // 화면에 보여줄 이미지
              loop: true        // 마지막 이미지에 도달시 첫이미지로 보이게 반복함
            })

       */}
      <div className="owl-carousel carousel-div owl-theme">
        <div className="position-relative mb-5">
          <img
            className="img-fluid rounded-circle border border-secondary p-2 mx-auto"
            src={require("../assets/img/testimonial/testimonial-1.jpg")}
            alt=""
          />
        </div>

        <div className="position-relative mb-5">
          <img
            className="img-fluid rounded-circle border border-secondary p-2 mx-auto"
            src={require("../assets/img/testimonial/testimonial-2.jpg")}
            alt=""
          />
        </div>

        <div className="position-relative mb-5">
          <img
            className="img-fluid rounded-circle border border-secondary p-2 mx-auto"
            src={require("../assets/img/testimonial/testimonial-3.jpg")}
            alt=""
          />
        </div>
      </div>
    </div>
  );
}

export default OwlCarouselCom;

 

결과

 

IsotopeCom 

 

libisotope 폴더 다운받아서 넣기

index.html 수정

-isotope + 이미지 겹침 문제 (바디위에)

 

pages

IsotopeCom.tsx 생성

// IsotopeCom.tsx : rfce
import React, { useEffect } from "react";
import initMain from "../assets/js/initMain";

function IsotopeCom() {
  useEffect(() => {
    initMain();
  }, []);

  return (
    <div>
      {/* isotope 소메뉴 부분 시작 */}
      <div className="row g-3">
        <div className="col-lg-12 text-center">
          <ul className="list-inline" id="portfolio-flters">
            {/* <!-- isotopo 필터 정의 --> */}
            <li className="mx-3 active" data-filter="*">
              All Projects
            </li>
            <li className="mx-3" data-filter=".first">
              Basic Develop
            </li>
            <li className="mx-3" data-filter=".second">
              Advanced Develop
            </li>
          </ul>
        </div>
      </div>
      {/* isotope 소메뉴 부분 끝 */}

      {/* <!-- isotope 필터 : .first, .second --> 시작 */}
      <div className="row g-3 portfolio-container">
        <div className="col-lg-3 col-md-6 portfolio-item first">
          <div className="portfolio-img rounded overflow-hidden">
            <img
              className="img-fluid"
              src={require("../assets/img/project/project-1.jpg")}
              alt=""
            />
          </div>
        </div>

        <div className="col-lg-3 col-md-6 portfolio-item second">
          <div className="portfolio-img rounded overflow-hidden">
            <img
              className="img-fluid"
              src={require("../assets/img/project/project-2.jpg")}
              alt=""
            />
          </div>
        </div>

        <div className="col-lg-3 col-md-6 portfolio-item first">
          <div className="portfolio-img rounded overflow-hidden">
            <img
              className="img-fluid"
              src={require("../assets/img/project/project-3.jpg")}
              alt=""
            />
          </div>
        </div>

        <div className="col-lg-3 col-md-6 portfolio-item second">
          <div className="portfolio-img rounded overflow-hidden">
            <img
              className="img-fluid"
              src={require("../assets/img/project/project-4.jpg")}
              alt=""
            />
          </div>
        </div>

        <div className="col-lg-3 col-md-6 portfolio-item first">
          <div className="portfolio-img rounded overflow-hidden">
            <img
              className="img-fluid"
              src={require("../assets/img/project/project-5.jpg")}
              alt=""
            />
          </div>
        </div>
      </div>
      {/* <!-- isotope 필터(정렬) : .first, .second --> 끝 */}
    </div>
  );
}

export default IsotopeCom;

initmain 수정

 

결과 (글자 클릭하면 카테고리에 맞게 사진 정렬됨)

 

EasingCom 

easing.zip
0.00MB

 

lib에 easing 폴더 만들고

위에 파일 넣기

index.html 수정

easing넣기 (body 위에)

 

pages에

EasingCom.tsx 생성

// EasingCom.tsx
import React, { useEffect } from 'react'
// 내가 만든 css
import "../assets/css/EasingCom.css";
import initMain from '../assets/js/initMain';

function EasingCom() {

  useEffect(()=>{
    initMain();
  },[])

  return (
    <div>
      <div id="boxing">
        <div id="box"></div>
      </div>
    </div>
  )
}

export default EasingCom

 

결과(계속 이동)

 

Datepicker

 

pages

Datepicker.tsx 생성

// Datepicker.tsx : rfce
import React, { useEffect, useRef, useState } from 'react'

function Datepicker() {

    // todo: 변수 정의
    const [jdate, setJdate] = useState("");

    // todo: 리액트에서 특정태그에 직접접근하는 방법 : const 변수명 = useRef()
    // todo: html input 태그에 속성 정의 : ref={변수명}
    // 바닐라 : querySelecter(선택자) 유사
    const datepicker = useRef<HTMLInputElement>(null);

    // todo: 함수 정의
    // 수동 바인딩 : 화면값 -> jdate 저장
    const onChangeJdate = (event:any) => {
        setJdate(event.target.value);
     }

    // 현재 달력에(ref={datepicker})) 선택된 값을 출력하는 버튼 함수
    const printDate = () => {
        // useRef 함수 값 가져오기 (달력 연결 : 달력 값)
        // es5 사용법 : 널리쉬 ?
        // 변수?속성명 -> 만약 변수가 null -> undefined 변경됨
        //               변수가 null 아니면 -> 속성명이 실행됨
        // alert(datepicker.current?.value);
        if(datepicker.current != null) {
            alert(datepicker.current.value); // 값 가져오기
        }
     }

    //  특정날짜를 달력 입력창에 표시하는 버튼 함수
    const setDate = () => {
        // (datepicker.current as any).value = "2023-10-30";
        if(datepicker.current != null) {
            datepicker.current.value = "2023-10-30";
        }
     }

    //  화면이 뜰때 달력(외부 lib) 만들기
     useEffect(()=>{
        $(function () {
            // 사용법 : $(선택자).datepicker({옵션});
            ($("#datepicker") as any).datepicker(
              // 날짜 포맷 지정
              {
                dateFormat: "yy-mm-dd", // 날짜 포맷
                showOn: "button",     // 입력창 옆에 달력 기본 버튼 보이기
                buttonImage:          // 버튼에 기본 이미지 넣기
              }
            );
          });        
     },[])

  return (
    <div className="container">
      <div className="form-group">
        <label htmlFor="daterange">daterange</label>
        {/* 달력 시작 */}
        <p>
          Date:
          <input
            type="text"
            id="datepicker"
            ref={datepicker}
            value={jdate}
            onChange={onChangeJdate}
          />
        </p>
        {/* 달력 끝 */}
        {/* 현재 달력에 선택된 값을 출력하는 버튼 : alert() */}
        <button
          className="btn btn-primary btn-sm mt-2 mb-2"
          onClick={printDate}
        >
          출력
        </button>
        &nbsp;&nbsp;
        {/* 특정날짜를 달력 입력창에 표시하는 버튼   */}
        <button
          className="btn btn-primary btn-sm mt-2 mb-2"
          onClick={() => setDate()}
        >
          날짜 지정
        </button>
        <br />
      </div>
    </div>
  )
}

export default Datepicker

index.html 수정 jquery css

바디에 jquery

 

결과

 

DaterangePicker

public 하위에

css js 폴더 만들고 파일 넣기

js.zip
0.03MB
css.zip
0.00MB

 

index.html

css, body 고치기 (DaterangePicker)

 

pages

DaterangePicker.tsx 만들기

// DaterangePicker.js
import React, { useEffect, useRef, useState } from "react";

/* eslint-disable */
function DaterangePicker() {
    // 달력 변수
  const [jdate, setJdate] = useState("");

  // 특수한 함수 : 리액트에서 지정한 태그에 직접 접근할때 사용
  const daterange = useRef<HTMLInputElement>(null);

//   화면이 뜰때 실행 : 달력 생성
  useEffect(() => {
    if ($("#daterange").length) { // daterange 있을때만 실행
        // 사용법 : $(선택자).daterangepicker({옵션})
      ($("#daterange") as any).daterangepicker({
        timePicker: true,             // 시간(시:분) 표현
        timePicker24Hour: true,       // 24시 표현
        timePickerSeconds: true,      // (시:분:초) 표현
        locale: {
          format: "YYYY-MM-DD HH:mm:ss", // 달력 포맷
        },
        // singleDatePicker: true // 달력 1개 사용
      });
    }
  },[]);

//   수동 바인딩
  const onChangeJdate = (event:React.ChangeEvent<HTMLInputElement>) => {
    setJdate(event.target.value);
  };
//   달력값 가져오기 : alert()
  const printDate =  () => {alert(daterange.current?.value)};

  return (
    <div className="container">
      <div className="form-group">
        <label htmlFor="daterange">daterange</label>
        {/* 사용법: ref=변수 */}
        {/* 달력 시작 */}
        <input
          type="text"
          className="form-control"
          id="daterange"
          name="daterange"
          value={jdate}
          onChange={onChangeJdate}
          ref={daterange}  
        />
        {/* 달력 끝 */}
        {/* 버튼 시작 */}
        <button className="btn btn-primary btn-sm mt-2 mb-2" onClick={printDate}>
          출력
        </button>
        {/* 버튼 끝 */}
        <br />
      </div>
    </div>
  );
}

export default DaterangePicker;

결과