React로 게임 형식의 웹 프로젝트를 개발하면서 웹 페이지 반응형으로 고정 비율로만 화면이 보이게 하는 기능을 개발했다.
이 기능을 개발하게 된 이유는 사실 작년에 비슷한 게임 형식의 웹 페이지를 만들었었는데, 너무나 다양한 브라우저 규격에 따라 의도한 1920x1080
비율로 보이지 않게되는 경우가 생겨 너무 안타까웠다...
이번 프로젝트는 언제 어디서 실행해도 디자이너들이 의도한 화면 비율로 보이게끔하기 위해 1920x1080
고정 규격으로 개발해보았다.
src/index.css 파일
#root
속 #App
이 정가운데 정렬이 되도록 작성했다.#root {
width: 100vw;
height: 100vh;
background: black;
display: flex;
align-items: center;
justify-content: center;
}
#App {
background: white;
position: relative;
}
src/App.js 파일
#App
의 가로를 화면에 꽉차게 설정하고, 세로를 비율에 맞게 조정했다.#App
의 세로를 화면에 꽉차게 설정하고, 가로를 비율에 맞게 조정하도록 했다.import React, { Component } from "react";
import './App.css';
class App extends Component {
render() {
return <div id="App"></div>;
}
componentDidMount() {
const FixRatio = () => {
const root = document.querySelector("#root");
const app = document.querySelector("#App");
// 가로를 화면에 딱 맞게
let width = root.clientWidth;
let height = width * 0.5625; // 1080 ÷ 1920 ≒ 0.5625
if (height > root.clientHeight) { // 설정된 세로 값이 화면보다 크다면
// 세로를 화면에 딱 맞게
height = root.clientHeight;
width = height * 1.7777; // 1920 ÷ 1080 ≒ 1.7777
}
// 설정한 값을 적용
app.style.width = `${width}px`;
app.style.height = `${height}px`;
};
window.onresize = FixRatio; // 화면의 사이즈가 변할 때마다 호출
FixRatio(); // 맨 처음 실행 될 때도 호출
}
}
export default App;
파일 구조
src
ㄴ services
ㄴ responsiveFrame
ㄴ index.js : 실제 기능을 구현한 코드
ㄴ style.css : 필요한 style 설정 파일
(처음 ver의 index.css와 내용이 같다)
src/services/responsiveFrame/index.js 파일
import "./style.css";
/**
* @param {number} 원본 화면의 width (px 단위)
* @param {number} 원본 화면의 height (px 단위)
* @return {function()} 현재 화면의 크기대로 frame을 조정하는 함수
*/
export const getResizeEventListener = (standardWidth, standardHeight) => {
const setFrames = () => {
const root = document.querySelector("#root");
const app = document.querySelector("#App");
let width = root.clientWidth;
let height = width * (standardHeight / standardWidth);
if (height > root.clientHeight) {
height = root.clientHeight;
width = height * (standardWidth / standardHeight);
}
app.style.width = `${standardWidth}px`;
app.style.height = `${standardHeight}px`;
};
return () => {
setFrames();
};
};
src/App.js 파일
import React, { Component } from "react";
import { getResizeEventListener } from "./services/responsiveFrame";
class App extends Component {
render() {
return <div id="App"></div>;
}
componentDidMount() {
const FixRatio = getResizeEventListener(1920, 1080);
window.onresize = FixRatio;
FixRatio();
}
}
export default App;
다음과 같이 px 단위로 크기가 설정된 요소가 있다면, #App
의 비율과는 상관없이 내부 요소는 크기가 고정된다.
import React, { Component } from "react";
import { getResizeEventListener } from "./services/responsiveFrame";
class App extends Component {
render() {
return (
<div id="App">
<div
style={{
position: "absolute",
background: "blue",
width: "500px",
height: "500px",
top: "300px",
left: "700px",
}}
></div>
</div>
);
}
componentDidMount() {
const FixRatio = getResizeEventListener(1920, 1080);
window.onresize = FixRatio;
FixRatio();
}
}
export default App;
위 영상처럼 되어 버린다.
이를 어떻게 구현해야할까 고민했다가, #App
의 width, height 값을 원하는 고정 사이즈로 설정하고, style의 zoom
속성을 사용해서 #App
의 크기가 조정되게 코드를 고쳐보았다.
src/services/responsiveFrame/index.js 파일
import "./style.css";
/**
* @param {number} 원본 화면의 width (px 단위)
* @param {number} 원본 화면의 height (px 단위)
* @return {function()} 현재 화면의 크기대로 frame을 조정하는 함수
*/
export const getResizeEventListener = (standardWidth, standardHeight) => {
return () => {
const root = document.querySelector("#root");
const app = document.querySelector("#App");
// 원하는 해상도로 width, height 고정
app.style.width = `${standardWidth}px`;
app.style.height = `${standardHeight}px`;
let width = root.clientWidth;
let height = width * (standardHeight / standardWidth);
// style.zoom을 이용하여, 화면을 크기를 조정
app.style.zoom = height / standardHeight;
if (height > root.clientHeight) {
height = root.clientHeight;
width = height * (standardWidth / standardHeight);
// style.zoom을 이용하여, 화면을 크기를 조정
app.style.zoom = width / standardWidth;
}
};
};
수정 결과, 원하는 대로 구현되었다.
감사합니다 😘