이전글 : [Canvas-불꽃놀이-04] Canvas 설정 - 물리적 크기와 CSS 크기
중요 이벤트 정의 (화면 전환, 리사이즈, 입력)
1. 이벤트 전달을 index.js에 캔버스 객체 생성하기
const canvas = new Canvas();
2. 화면 전환 (MDN-hashchange)
- 사용자가 입력을 하면 캔버스 화면으로 전환이 필요해 가장 간단한 방법인 hashchange 이벤트를 사용하기로 했다.
// constants.js
// hashchange에 필요한 상수 정의
const FIREWORKS = "fireworks";
export const LOCATION_HASH = {
HOME: "home",
FIREWORKS,
FIREWORKS_HASH: `#${FIREWORKS}`,
};
- 사용의 편의를 위해 html 요소를 미리 불러와 객체로 만들었다
// index.js
// 사용의 편의를 위해 html 객체를 domElements 객체에 저장하였다.
const domElements = {
body: document.body,
home: document.getElementById(HOME),
fireworks: document.getElementById(FIREWORKS),
};
- 현재 해쉬값이 fireworks 화면인지 판별하기 위한 메서드 생성했다.
const isHashFireworks = () => location.hash == FIREWORKS_HASH;
- 맨 처음 브라우저가 로드되거나 새로고침 될 때 불꽃놀이 화면이면 홈화면으로 이동시키기로 결정하였다.
- body의 CSS visibility 속성을 hidden으로 했다가 로드 완료 후 visible로 바꿔준 코드를 추가한 이유는 로드되기 전 미리 콘텐츠가 보여 사라졌다 다시 나타나는 현상을 방지하기 위해서다.
body {
/* 모든 스타일과 JavaScript가 로드된 후 화면을 보여주기 위해 visibility를 hidden으로 설정 */
visibility: hidden;
}
const handleLoad = () => {
// 모든 스타일과 JavaScript를 로드한 후에 콘텐츠를 보여주기 위해 추가
domElements.body.style.visibility = "visible";
// 로드 시 hash가 #fireworks이면 홈화면으로 돌아간다.
if (isHashFireworks()) {
location.hash = "";
}
});
window.addEventListener("load", handleLoad);
- 해쉬값에 따라 화면을 다르게 보여줘야 하므로 화면 전환을 위한 메서드 생성했다.
- js 파일 맨 마지막에 switchScreen 메서드를 실행시킨 이유는 DOM 요소들이 먼저 로드된 후에 해당 요소를 조작할 수 있기 때문이다.
const switchScreen = (screen) => {
domElements.home.style.display = screen == HOME ? "flex" : "none";
domElements.fireworks.style.display = screen == FIREWORKS ? "block" : "none";
};
// 파일 맨 마지막에서 모든 dom 요소가 로드된 다음 호출
switchScreen(isHashFireworks() ? FIREWORKS : HOME);
3. 리사이즈 시 캔버스 재설정
- 브라우저 창 크기가 변경되면 캔버스를 새로운 크기에 맞게 업데이트 해야 현재 사이즈에 맞는 애니메이션을 감상할 수 있다.
- 따라서 리사이즈 이벤트가 발생하면 캔버스의 크기, 좌표 위치, 모바일 여부, 텍스트 픽셀 데이터 등의 크기 관련 속성을 재설정하여 변경된 사이즈에 맞게 애니메이션이 이루어지도록 해야 한다.
- 리사이즈 이벤트는 창 크기를 잡고 늘리는 동안 여러 번 발생할 수 있다. 따라서 일정 시간이 지난 다음에만 캔버스를 업데이트하여 불필요한 메서드 호출을 줄이고 성능을 최적화한다.
// index.js
// 리사이즈 보류 시간을 저장할 변수
let resizeTimeout;
// 창 크기 변경시 이벤트 처리
const handleResize = () => {
// 이전에 예약된 타이머를 취소하여 중복 실행 방지
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => { // RESIZE_DELAYms가 지나고
if (isHashFireworks()) { // hash가 fireworks일때만
canvas.init(); // 캔버스 속성을 재설정하고
canvas.createTextDatas(); // 텍스트 픽셀 데이터도 다시 업데이트 한다.
}
}, RESIZE_DELAY); // RESIZE_DELAYms 지연
});
window.addEventListener("resize", handleResize);
4. 사용자 입력에 따른 hashchange
- hashchange를 완성했으니 이제 사용자의 입력을 받아서 처리하는 이벤트를 추가해야 한다.
- domElements에 form과 input html 요소를 추가한다.
// 앞서 생성한 domElements 변수에 추가
inputForm: document.getElementById("input_form"),
userInput: document.getElementById("user_input"),
- form 태그를 사용하여 입력 후 제출 이벤트를 관리하므로 submit 이벤트를 추가한다.
const handleSubmit = (e) => {
// 기본적으로 브라우저에서 발생하는 submit 동작을 방지(js 로직으로 직접 처리할수 있게 설정)
e.preventDefault();
// 사용자의 입력값을 가져와 앞, 뒤 공백을 제거해준다.
const userInputValue = domElements.userInput.value.trim();
// 입력값이 있을 경우에만 캔버스 인스턴스에 입력값을 업데이트 시켜준다.
if (userInputValue.length > 0 && userInputValue.length <= 10) {
canvas.text = userInputValue;
canvas.textLength = userInputValue.length;
// 입력값을 넘겨준 후 hash를 불꽃놀이 화면으로 전환할 수 있게 바꿔준다.
location.hash = FIREWORKS_HASH;
} else {
alert("글자를 입력해주세요. 1~10글자 까지 입력 가능합니다.");
}
});
domElements.inputForm.addEventListener("submit", (e) => handleSubmit(e));
- 캔버스 객체에 사용자가 입력한 내용을 저장하기 위해 멤버 변수를 추가하고 추후 객체 폴링 초기화를 위해 미리 캔버스 멤버변수를 초기화 메서드를 만들어 constructor에서 실행시킨다.
class Canvas extends CanvasOption {
constructor() {
super();
// Canvas class 멤버 변수 초기화
this.initCanvasVars();
}
// 멤버 변수 초기화 메서드
initCanvasVars() {
this.text = "";
this.textLength = 0;
}
}
- submit 버튼 이벤트 완료 후 hashchange 이벤트가 발생하니 hashchange 이벤트도 추가한다.
const handleHashChange = () => {
// fireworks로 hashchange가 발생할경우
if (isHashFireworks()) {
canvas.init(); // 캔버스를 초기화 시켜주고
switchScreen(FIREWORKS);// fireworks 화면으로 전환한다.
} else {
// home으로 hashchange가 발생할경우 불꽃놀이 이벤트가 발생하기 전 상태로 되돌아가야 하므로
// 사용자 입력값과 캔버스 멤버 변수를 초기화 시켜준다.
domElements.userInput.value = "";
canvas.initCanvasVars();
switchScreen(HOME); // home 화면으로 전환한다.
}
});
window.addEventListener("hashchange", handleHashChange);
5. Input maxLength 오류 수정 (+추가내용)
한글 입력 시 maxLength를 10으로 설정해도 마지막 한 글자가 더 입력하는 오류가 있다.
모바일에서는 maxLength가 동작하지 않아 무제한으로 입력이 가능한 걸 확인하였다.
이를 해결하기 위해 input 이벤트 발생 시 글자 길이를 확인하여 10글자가 넘어갈 경우 substr 메서드를 사용해 텍스트의 길이를 조절한다.
// index.js
const handleInput = (e) => {
const { value, maxLength } = e.target;
if (value.length > maxLength) {
e.target.value = value.substr(0, maxLength); // maxLength를 넘을 경우 10글자까지 잘라낸다.
}
};
domElements.userInput.addEventListener("input", (e) => handleInput(e));
Github 링크
'Canvas > 불꽃놀이 프로젝트' 카테고리의 다른 글
[Canvas-불꽃놀이-07] 불꽃놀이 Particle들의 부모 클래스 (1) | 2024.11.18 |
---|---|
[Canvas-불꽃놀이-06] TextData 클래스 (2) | 2024.11.18 |
[Canvas-불꽃놀이-04] Canvas 설정 - 물리적 크기와 CSS 크기 (0) | 2024.11.17 |
[Canvas-불꽃놀이-03] Canvas 설정하기 (4) | 2024.11.16 |
[Canvas-불꽃놀이-02] UI 구성 (3) | 2024.11.16 |