[Canvas-불꽃놀이-05] index.js에서 중요 이벤트 정의

이전글 : [Canvas-불꽃놀이-04] Canvas 설정 - 물리적 크기와 CSS 크기

 

[Canvas-불꽃놀이-04] Canvas 설정 - 물리적 크기와 CSS 크기

이전 글 : 2024.11.16 - [개발/Canvas] - [Canvas-불꽃놀이-03] Canvas 설정하기 [Canvas-불꽃놀이-03] Canvas 설정하기이전글 : 2024.11.15 - [개발/Canvas] - [Canvas-불꽃놀이-02] UI 구성 [Canvas-불꽃놀이-02] UI 구성이전

jinsk-joy.tistory.com

 

중요 이벤트 정의 (화면 전환, 리사이즈, 입력)

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 링크
 

GitHub - jinsk9268/text-fireworks

Contribute to jinsk9268/text-fireworks development by creating an account on GitHub.

github.com