원안에 텍스트 넣기
dev | 2012-10-25
H3 2012 메인페이지에는 글자가 원안에 들어가는 독특한 디자인이 사용되었다. CSS에는 원으로 글자를 배치시키는 기능은 없기 때문에 고민이 되는 부분이었다. 가장 간단하게는 텍스트를 모두 가운데 정렬 한 다음에 모양에 많게 줄바꿈을 해주면 구현이 가능하다. 하지만 세션의 제목이 나중에 변경될 수도 있다는 얘기를 듣고 이런 노가다성 해결책 말고 다른 방법을 찾아보기로 하였다.
모양이나 사진의 외곽선을 따라서 글자가 배치되는 디자인은 잡지책에서도 쉽게 볼 수 있다. 문제는 HTML요소는 모두 사각형으로 그려지기 때문에 이러한 모양 정보를 넣을수 없다는데 있다. 하지만 점이 만나서 선이 되듯이 테이블 태그로 그림 그리듯이...는 아니고 박스의 크기를 잘 조절하면 성능과 모양 사이에서 적절한 타협점이 있을 수 있다는 생각이 들었다. 텍스트 배치는 노멀 플로우(normal flow)에 영향을 미치는 플롯(float)을 사용하면 되겠다는 생각을 하고 손으로 값을 계산에서 테스트를 해봤다.
아이디어는 간단하다. 텍스트가 들어가야할 원을 빼고는 나머지 공간을 플롯된 박스로 채우는 것이다. 그러면 텍스트는 자연스럽게 원 안에 배치될 것이다. 박스를 번갈아서 왼쪽, 오른쪽으로 배치하면서 박스 길이만 적절하게 조절하면 원 모양을 그리는 것이 가능했고 텍스트도 잘 배치가 됐다. 브라우저 호환성도 IE8이상은 합격이었다. 처음에는 IE8 이상에서만 정상적으로 보였는데 지금은 호환성에 문제 있는 부분들을 수정해서 여기서 제공하고 있는 코드는 IE6 이상에서 잘 작동하는 것을 확인하였다.
어려운 난관이 박스의 너비를 계산하는 것이었는데 중학교(-_-;;)때의 기억을 더듬어서 계산을 해 보았다. 상단으로 부터의 거리를 y라고 하고 구하고자 하는 값을 x라고 한다음 원주와 박스가 만나는 점을 기준으로 생성되는 삼각형의 내각을 θ라고 하면 아래와 같은 그림을 그릴 수 있다.
직각 삼각형의 특성에서 sin(θ) = y / r 이고 cos(θ) = (r – x) / r 이다. sin2(θ) + cos2(θ) = 1 이기 때문에 (y / r)2 + {(r – x) / r}2 = 1 이고 이를 y에 대해서 정리를 하면 y = SQRT(x * (2 * r – x)) 가 된다. 풀어놓고보면 간단한데 처음 계산할 당시에는 기억안나서 엄청 삽질했다.
너비를 구했으니 이제 적절한 간격으로 y에 해당하는 박스를 왼쪽, 오른쪽으로 번갈아서 넣어주면 된다. 전체 코드는 아래와 같다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>원안에 텍스트 넣기</title>
<style type="text/css">
#session {
width: 350px;
}
#session div {
background-color: #0c0;
}
</style>
</head>
<body>
<div id="session">1절
동해물과 백두산이 마르고 닳도록
하느님이 보우하사 우리 나라 만세.
후렴: 무궁화 삼천리 화려강산
대한사람 대한으로 길이 보전하세.
2절
남산위에 저 소나무 철갑을 두른 듯
바람서리 불변함은 우리 기상일세.
후렴: 무궁화 삼천리 화려강산
대한사람 대한으로 길이 보전하세.
3절
가을하늘 공활한데 높고 구름없이.
밝은 달은 우리 가슴 일편 단심일세.
후렴: 무궁화 삼천리 화려강산
대한사람 대한으로 길이 보전하세.
4절
이 기상과 이 맘으로 충성을 다하여
괴로우나 즐거우나 나라 사랑하세.
후렴: 무궁화 삼천리 화려강산
대한 사람 대한으로 길이 보전하세</div>
<script type="text/javascript">
(function () {
var el = document.getElementById('session');
if (!el) {
return false;
}
var width = el.offsetWidth;
// el.style.height = width + 'px';
var blocker = {};
blocker.html = [];
blocker.padding = 5;
var r = width / 2;
for (var i = 0; i <= width; i += blocker.padding) {
blocker.width = r - Math.sqrt(i * (2 * r - i)) + blocker.padding;
if (blocker.width > r) {
blocker.width = r;
}
blocker.html.push('<div style="clear: left; float: left; width: ' + blocker.width + 'px; height: ' + blocker.padding + 'px; overflow: hidden;"></div><div style="clear: right; float: right; width: ' + blocker.width + 'px; height: ' + blocker.padding + 'px; overflow: hidden;"></div>');
}
el.innerHTML = blocker.html.join('') + el.innerHTML;
})();
</script>
</body>
</html>
아래와 같이 랜더링 된다. 녹색으로 칠해진 div 색을 없애면 원하는 대로 원 모양으로 텍스트가 배치된 것을 볼 수 있다.
이 글은 kth 개발자 블로그에 실린 글입니다.
Comments
ㅡ.ㅡ 아쒸. 위에서부터 차근차근 읽고 있었는데...... 싸인, 코싸인에서 포기.... 배신당한 느낌. ㅋㅋ
하아; 역시 싸인, 코싸인에서 막히네요. 누가.. 사칙연산만 알면 사는데 지장 없다 했는가..ㅠ
수능때 삼각함수 완전 포기하고 봤는데 캔버스도 그렇고 큰일났다... ㅠㅠ