로또 전호를 자동생성하는 함수를 하나 만들어 보자.
LottoGenerator.js 파일을 만듭니다.
|
let lottoGenerator = () =>{
let set = new Set();
while(set.size<6)set.add(parseInt(Math.random()*45)+1); // 중복되지 않는 5개 숫자 만들기
let ar = [...set]; // 배열로 복사
ar = ar.sort((a,b)=>a-b); // 숫자 정렬
return ar; // 배열 리턴
}
export default lottoGenerator;
|
Set객체는 중복을 허용하지 않는 객체입니다.
Math.random()*45)+1 : 1~45까지의 정수 난수 생성
while(set.size<6)set.add(parseInt(Math.random()*45)+1);
내용의 개수가 6개가 될때 까지 난수로 채워주면 중복되지 않는 숫자 6개가 생성이 됩니다.
Lotto.js 파일을 만듭니다.
|
import lottoGenerator from './LottoGenerator';
export const Lotto1 = () =>{
return lottoGenerator().map((n) => `${n}`.padStart(2, 0) + ' ');
}
|
문자열.padStart(길이, 앞에 채울 문자);
문자열.padEnd(길이, 뒤에 채울 문자);
숫자를 칸을 맞추기 위해 2자리 숫자로 만듭니다. 두자리 숫자가 아닐경우 앞자리 빈칸을 0으로 채웁니다.
App.js 파일을 만듭니다.
|
import { Lotto1 } from "./Lotto";
const App = ()=>{
return <Lotto1/>
}
export default App;
|
index.js 파일을 만듭니다.
|
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.querySelector("#app"));
root.render(
<React.StrictMode>
<App/>
</React.StrictMode>
);
|
index.html 파일을 만듭니다.
|
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
|
실행 결과입니다.

다음의 압축 파일을 풀어 이미지 파일을 public/images/numbers 폴더에 넣습니다.
직접 이미지 태그를 사용해서 넣으려면 public 폴더에 위치해야 합니다.
다음 6개의 파일은 src/ images/numbers 폴더에 넣습니다.
src의 css파일에서 url()로 추가하거나 import 명령으로 이미지를 추가하려면 src 폴더에 위치해야 합니다.
조금 더 이쁘게 만들어 보도록 하겠습니다.
Lotto.js 파일을 수정합니다.
|
import lottoGenerator from './LottoGenerator';
export const Lotto1 = () => {
return lottoGenerator().map((n) => `${n}`.padStart(2, 0) + ' ');
}
const Number = ({ number }) => {
let num = `${number}`.padStart(2, 0);
let src = `./images/numbers/ball_${num}.png`;
return <img src={src} alt={num} style={{ margin: "2px" }} />
}
export const Lotto2 = () => {
return lottoGenerator().map((n) => <Number number={n} key={n} />);
}
|
번호에 해당하는 이미지를 불러서 출력하는 Number라는 컴포넌트를 만들어 출력했습니다.
App.js 파일을 수정합니다.
|
import { Lotto1, Lotto2 } from "./Lotto";
import logo1 from './images/numbers/logo-header.png'
import logo2 from './images/numbers/img_gnb_game1.jpg'
const App = ()=>{
return(
<>
<img src={logo1} alt={logo1}/>
<img src={logo2} alt={logo2}/>
<br/>
<Lotto1/>
<br/>
<Lotto2/>
</>
)
}
export default App;
|
실행 결과입니다.

이미지가 변경되다가 지정 시간이 되면 멈추는 애니메이션을 추가해 보겠습니다.
Lotto.js 파일을 수정합니다.
|
import lottoGenerator from './LottoGenerator';
export const Lotto1 = () => {
return lottoGenerator().map((n) => `${n}`.padStart(2, 0) + ' ');
}
const Number = ({ number }) => {
let num = `${number}`.padStart(2, 0);
let src = `./images/numbers/ball_${num}.png`;
return <img src={src} alt={num} style={{ margin: "2px" }} />
}
export const Lotto2 = () => {
return lottoGenerator().map((n) => <Number number={n} key={n} />);
}
// 번호 이미지가 계속 바뀌다가 지정 번호를 이미지로 출력해주는 컴포넌트
const Number2 = ({number, time }) => {
const [idx, setIdx] = useState(1);
const [src, setSrc] = useState(`./images/numbers/ball_01.png`);
const interval = useRef(1);
useEffect(() => {
// 0.1초 간격으로 01~45번 이미지로 변경됩니다.
interval.current = setInterval(() => {
setIdx((idx+1)%45+1);
setSrc( `./images/numbers/ball_` + `${idx}`.padStart(2, 0) + `.png`);
}, 100);
// time 속성 값이 초 단위 입니다. 지정 시간 후 타이머를 종료하고 지정번호로 바꿉니다.
setTimeout(() => {
clearInterval(interval.current);
setSrc( `./images/numbers/ball_` + `${number}`.padStart(2, 0) + `.png`);
}, time * 1000)
return () => {
clearInterval(interval.current);
};
}, [idx, src, number, time]);
return <img src={src} alt={src} style={{ margin: "2px" }} />
}
export const Lotto3 = () => {
return lottoGenerator().map((n, index) => <Number2 number={n} time={index+1} key={n}/>);
}
|
번호에 해당하는 이미지를 불러서 출력하는 Number라는 컴포넌트를 만들어 출력했습니다.
App.js 파일을 수정합니다.
|
import { Lotto1, Lotto2 } from "./Lotto";
import logo1 from './images/numbers/logo-header.png'
import logo2 from './images/numbers/img_gnb_game1.jpg'
const App = ()=>{
return(
<>
<img src={logo1} alt={logo1}/>
<img src={logo2} alt={logo2}/>
<br/>
<Lotto1/>
<br/>
<Lotto2/>
<br/>
<Lotto3/>
</>
)
}
export default App;
|
실행 결과입니다.
이미지가 바뀌다가 1초 간격으로 하나씩 멈춰집니다.

다음은 스크롤을 해보도록 하겠습니다.
표시될 크기보다 커다란 배경이미지의 top/left 값을 변경해서 일부분 만 보이게 하도록하면 스크롤 기능을 구현 할 수 있습니다.
ScrollNumber.css 파일을 다음과 같이 만듭니다.
|
.numbers {
width: 52px;
height: 52px;
margin: 2px;
background-repeat: no-repeat;
display: inline-block;
}
.numbersh {
background-image: url("./images/numbers/ballh.jpg");
}
.numbersv {
background-image: url("./images/numbers/ballv.jpg");
}
.lottos {
width: 80px;
height: 80px;
margin: 2px;
background-repeat: no-repeat;
display: inline-block;
}
.lottosh {
background-image: url("./images/numbers/lotto_ball_horz.jpg");
}
.lottosv {
background-image: url("./images/numbers/lotto_ball_vert.jpg");
}
|
Lotto.js 파일을 수정합니다.
|
import { useEffect, useRef, useState } from 'react';
import lottoGenerator from './LottoGenerator';
import './ScrollNumber.css'
export const Lotto1 = () => {
return lottoGenerator().map((n) => `${n}`.padStart(2, 0) + ' ');
}
// 번호를 이미지로 출력해주는 컴포넌트
const Number = ({ number }) => {
let num = `${number}`.padStart(2, 0);
let src = `./images/numbers/ball_${num}.png`;
return <img src={src} alt={num} style={{ margin: "2px" }} />
}
export const Lotto2 = () => {
return lottoGenerator().map((n) => <Number number={n} key={n}/>);
}
// 번호 이미지가 계속 바뀌다가 지정 번호를 이미지로 출력해주는 컴포넌트
const Number2 = ({number, time }) => {
const [idx, setIdx] = useState(1);
const [src, setSrc] = useState(`./images/numbers/ball_01.png`);
const interval = useRef(1);
useEffect(() => {
// 0.1초 간격으로 01~45번 이미지로 변경됩니다.
interval.current = setInterval(() => {
setIdx((idx+1)%45+1);
setSrc( `./images/numbers/ball_` + `${idx}`.padStart(2, 0) + `.png`);
}, 100);
// time 속성 값이 초 단위 입니다. 지정 시간 후 타이머를 종료하고 지정번호로 바꿉니다.
setTimeout(() => {
clearInterval(interval.current);
setSrc( `./images/numbers/ball_` + `${number}`.padStart(2, 0) + `.png`);
}, time * 1000)
return () => {
clearInterval(interval.current);
};
}, [idx, src, number, time]);
return <img src={src} alt={src} style={{ margin: "2px" }} />
}
export const Lotto3 = () => {
return lottoGenerator().map((n, index) => <Number2 number={n} time={index+1} key={n}/>);
}
// 위로 스크롤됩니다. 이미지크기가 52px이므로 52를 곱해서 스크롤을 처리했습니다.
const ScrollNumberV = ({time=1, number=1}) => {
const [top, setTop] = useState(-1);
const interval = useRef(1);
let style = {backgroundPosition: `0px ${-1*top}px` }
useEffect(() => {
interval.current = setInterval(() => {
setTop(top + 10);
if (top >= 52*45) { // 이미지 끝에 도달하면
setTop(0);
}
}, 20);
setTimeout(()=>{
clearInterval(interval.current);
setTop((number-1)*52)
}, time*1000);
return () => {
clearInterval(interval.current);
}
}, [top, number, time]);
return <div className="numbers numbersv" style={style}></div>
}
export const Lotto4 = () => {
return lottoGenerator().map((n, index) => <ScrollNumberV number={n} time={index+1} key={n}/>);
}
// 왼쪽으로 스크롤됩니다.
const ScrollNumberH = ({time=1, number=1}) => {
const [left, setLeft] = useState(-1);
const interval = useRef(1);
let style = {backgroundPosition: `${-1*left}px 0px` }
useEffect(() => {
interval.current = setInterval(() => {
setLeft(left + 10);
if (left >= 52*45) {
setLeft(0);
}
}, 20);
setTimeout(()=>{
clearInterval(interval.current);
setLeft((number-1)*52)
}, time*1000);
return () => {
clearInterval(interval.current);
}
}, [left, number, time]);
return <div className="numbers numbersh" style={style}></div>
}
export const Lotto5 = () => {
return lottoGenerator().map((n, index) => <ScrollNumberH number={n} time={index+1} key={n}/>);
}
// 위로 스크롤됩니다. 이미지크기가 80px이므로 80을 곱해서 스크롤을 처리했습니다.
const ScrollNumberV2 = ({time=1, number=1}) => {
const [top, setTop] = useState(-1);
const interval = useRef(1);
let style = {backgroundPosition: `0px ${-1*top}px` }
useEffect(() => {
interval.current = setInterval(() => {
setTop(top + 10);
if (top >= 80*45) {
setTop(0);
}
}, 20);
setTimeout(()=>{
clearInterval(interval.current);
setTop((number-1)*80)
}, time*1000);
return () => {
clearInterval(interval.current);
}
}, [top, number, time]);
return <div className="lottos lottosv" style={style}></div>
}
export const Lotto6 = () => {
return lottoGenerator().map((n, index) => <ScrollNumberV2 number={n} time={index+1} key={n}/>);
}
// 왼쪽으로 스크롤됩니다.
const ScrollNumberH2 = ({time=1, number=1}) => {
const [left, setLeft] = useState(-1);
const interval = useRef(1);
let style = {backgroundPosition: `${-1*left}px 0px` }
useEffect(() => {
interval.current = setInterval(() => {
setLeft(left + 10);
if (left >= 80*45) {
setLeft(0);
}
}, 20);
setTimeout(()=>{
clearInterval(interval.current);
setLeft((number-1)*80)
}, time*1000);
return () => {
clearInterval(interval.current);
}
}, [left, number, time]);
return <div className="lottos lottosh" style={style}></div>
}
export const Lotto7 = () => {
return lottoGenerator().map((n, index) => <ScrollNumberH2 number={n} time={index+1} key={n}/>);
}
|
번호에 해당하는 이미지를 불러서 출력하는 Number라는 컴포넌트를 만들어 출력했습니다.
App.js 파일을 수정합니다.
|
import { Lotto1, Lotto2 } from "./Lotto";
import logo1 from './images/numbers/logo-header.png'
import logo2 from './images/numbers/img_gnb_game1.jpg'
const App = ()=>{
return(
<>
<img src={logo1} alt={logo1}/>
<img src={logo2} alt={logo2}/>
<br/>
<br/>
<Lotto1/>
<br/>
<Lotto2/>
<br/>
<Lotto3/>
<br/>
<Lotto4/>
<br/>
<Lotto5/>
<br/>
<Lotto6/>
<br/>
<Lotto7/>
</>
)
}
export default App;
|
실행 결과입니다.
실행해 보시면 스크롤되는 결과를 확인하실 수 있습니다.

'Front End > React' 카테고리의 다른 글
| [React Exam 39] 가위바위보 게임 만들기 (1) | 2024.11.05 |
|---|---|
| [React Exam 38] 로또 번호 자동 생성기 만들기 2 (0) | 2024.11.05 |
| [React Exam 36] 시계 만들어보기 (5) | 2024.11.04 |
| [React Exam 35] Counter 만들어보기 (1) | 2024.11.04 |
| [React Exam 34] map()을 이용한 10간(十干)/ 12지(十二支) 나열하기 (0) | 2024.11.01 |