๐ ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ : ์ง์งํ ๋ค์ด์ด๊ทธ๋จ์ ์ธํฐ๋ํฐ๋ธ ๋ฒกํฐ ์ ๋๋ฉ์ด์ ์ผ๋ก
์๋ ํ์ธ์, ์ง์งํ ์ ํธ๊ฐ ์ฌ๋ฌ๋ถ! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฌ๋ฌ๋ถ์ ๋ชจ์ จ์ต๋๋ค. ๋ฐ๋ก ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ์ธํฐ๋ํฐ๋ธ ๋ฒกํฐ ์ ๋๋ฉ์ด์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ๐จโจ ์ด ๊ธ์ ํตํด ์ฌ๋ฌ๋ถ์ ์ง์งํ์ ๋ณต์กํ ๊ฐ๋ ์ ์๊ฐ์ ์ผ๋ก ๋ฉ์ง๊ฒ ํํํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ๋๋ค. ๋ง์น ํ์ฐ์ด ํญ๋ฐํ๋ฏ ์ฌ๋ฌ๋ถ์ ์ฐฝ์๋ ฅ๋ ํญ๋ฐํ ์ค๋น๊ฐ ๋์ จ๋์? ๊ทธ๋ผ ์์ํด๋ณผ๊น์!
๐ ์์๋์ธ์: ์ด ๊ธ์ ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ '์ง์์ธ์ ์ฒ' ๋ฉ๋ด์ ๋ฑ๋ก๋ ์์ ์ ๋๋ค. ์ฌ๋ฅ๋ท์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฑฐ๋ํ๋ ํ๋ซํผ์ผ๋ก, ์ฌ๋ฌ๋ถ์ ์ง์๊ณผ ๊ธฐ์ ์ ๋๋๊ณ ์ฑ์ฅํ ์ ์๋ ํ๋ฅญํ ๊ณต๊ฐ์ ๋๋ค.
1. ํ์ฐ ๋ถ์ถ์ ๊ธฐ์ด: ์ง์งํ์ ์ดํด
ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ์์ํ๊ธฐ ์ ์, ๋จผ์ ํ์ฐ ๋ถ์ถ์ ๊ธฐ๋ณธ์ ์ธ ๋ฉ์ปค๋์ฆ์ ์ดํดํด์ผ ํฉ๋๋ค. ํ์ฐ์ ์ง๊ตฌ ๋ด๋ถ์ ๋ง๊ทธ๋ง๊ฐ ์งํ๋ฉด์ผ๋ก ๋ถ์ถ๋๋ ํ์์ ๋งํฉ๋๋ค. ์ด ๊ณผ์ ์ ๋งค์ฐ ๋ณต์กํ๊ณ ๋ค์ํ ์์ธ๋ค์ด ์์ฉํ์ง๋ง, ์ฐ๋ฆฌ์ ์๋ฎฌ๋ ์ด์ ์ ์ํด ํต์ฌ์ ์ธ ์์๋ค์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
- ๋ง๊ทธ๋ง์ ํ์ฑ: ์ง๊ตฌ ๋ด๋ถ์ ๊ณ ์จ, ๊ณ ์ ํ๊ฒฝ์์ ์์์ด ๋ น์ ํ์ฑ
- ๋ง๊ทธ๋ง์ ์์น: ๋ฐ๋ ์ฐจ์ด์ ์๋ ฅ์ผ๋ก ์ธํด ์งํ๋ฉด์ผ๋ก ์์น
- ํ์ฐ ๋ถ์ถ: ๋ง๊ทธ๋ง๊ฐ ์งํ๋ฉด์ ๋๋ฌํ์ฌ ๋ถ์ถ
- ํ์ฐ ๊ตฌ์กฐ ํ์ฑ: ๋ถ์ถ๋ ๋ฌผ์ง์ด ์์ฌ ํ์ฐ์ฒด ํ์ฑ
์ด๋ฌํ ๊ณผ์ ์ ์๊ฐํํ๊ธฐ ์ํด, ์ฐ๋ฆฌ๋ SVG(Scalable Vector Graphics)๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. SVG๋ ๋ฒกํฐ ๊ธฐ๋ฐ์ ๊ทธ๋ํฝ์ ํํํ๋ XML ํฌ๋งท์ผ๋ก, ํ๋ํด๋ ๊นจ์ง์ง ์๋ ์ ๋ช ํ ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ ์ ๋๋ฉ์ด์ ํจ๊ณผ๋ฅผ ์ฝ๊ฒ ์ ์ฉํ ์ ์์ด, ๋์ ์ธ ํ์ฐ ๋ถ์ถ ๊ณผ์ ์ ํํํ๊ธฐ์ ๋ฑ ๋ง์ฃ !
์์ SVG ์ ๋๋ฉ์ด์ ์ ํ์ฐ ๋ถ์ถ์ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ค๋๋ค. ๋ง๊ทธ๋ง ์ฑ๋ฒ์์ ์์๋ ๋ง๊ทธ๋ง๊ฐ ์์นํ์ฌ ์งํ๋ฉด์ผ๋ก ๋ถ์ถ๋๋ ๊ณผ์ ์ ๊ฐ๋จํ๊ฒ ํํํ์ต๋๋ค. ์ด์ ์ด ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๋ฐํ์ผ๋ก, ๋ ๋ณต์กํ๊ณ ์์ธํ ์๋ฎฌ๋ ์ด์ ์ ๋ง๋ค์ด ๋ณผ ๊ฑฐ์์.
2. SVG ๊ธฐ์ด: ๋ฒกํฐ ๊ทธ๋ํฝ์ ์ธ๊ณ
SVG๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ๋ง๋ค๊ธฐ ์ ์, SVG์ ๊ธฐ๋ณธ ๊ฐ๋ ๊ณผ ์์๋ค์ ๊ฐ๋จํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. SVG๋ XML ๊ธฐ๋ฐ์ ๋ฒกํฐ ์ด๋ฏธ์ง ํฌ๋งท์ผ๋ก, ์น์์ ํ์ฅ ๊ฐ๋ฅํ ๊ทธ๋ํฝ์ ๋ง๋๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
SVG์ ์ฃผ์ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ํ์ฅ์ฑ: ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ๋ณ๊ฒฝํด๋ ํ์ง ์์ค์ด ์์ต๋๋ค.
- ํ ์คํธ ํธ์ง ๊ฐ๋ฅ: SVG ๋ด์ ํ ์คํธ๋ ๊ฒ์ ์์ง์ด ์ฝ์ ์ ์์ต๋๋ค.
- ์์ ํ์ผ ํฌ๊ธฐ: ๋ณต์กํ ๊ทธ๋ํฝ๋ ์๋์ ์ผ๋ก ์์ ํ์ผ ํฌ๊ธฐ๋ก ํํ ๊ฐ๋ฅํฉ๋๋ค.
- ์ ๋๋ฉ์ด์ ์ง์: CSS๋ JavaScript๋ฅผ ์ฌ์ฉํด ์ฝ๊ฒ ์ ๋๋ฉ์ด์ ์ ์ ์ฉํ ์ ์์ต๋๋ค.
SVG์ ๊ธฐ๋ณธ ์์๋ค์ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
<svg width="800" height="600" viewBox="0 0 800 600">
<!-- SVG ๋ด์ฉ -->
</svg>
์ด๊ฒ์ด SVG์ ๊ธฐ๋ณธ ๊ตฌ์กฐ์ ๋๋ค. width์ height๋ SVG์ ํฌ๊ธฐ๋ฅผ, viewBox๋ SVG ์ขํ ์์คํ ์ ์ ์ํฉ๋๋ค.
์ฃผ์ SVG ๋ํ ์์:
- <rect>: ์ง์ฌ๊ฐํ
- <circle>: ์
- <ellipse>: ํ์
- <line>: ์
- <polyline>: ์ฐ๊ฒฐ๋ ์ง์ ๋ค
- <polygon>: ๋ค๊ฐํ
- <path>: ๋ณต์กํ ๊ฒฝ๋ก
์ด์ ์ด ์์๋ค์ ์ฌ์ฉํด ๊ฐ๋จํ ํ์ฐ ๋ชจํ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค:
์ด ์์ ์์๋ ๋ค์ํ SVG ์์๋ค์ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ํ์ฐ ๋ชจํ์ ๋ง๋ค์์ต๋๋ค. <rect> ์์๋ก ํ๋๊ณผ ๋ ์ ํํํ๊ณ , <polygon>์ผ๋ก ํ์ฐ์ ํํ๋ฅผ, <ellipse>๋ก ๋ถํ๊ตฌ๋ฅผ ๊ทธ๋ ธ์ต๋๋ค. ๋ํ <circle> ์์์ ์ ๋๋ฉ์ด์ ์ ์ฌ์ฉํ์ฌ ์ฐ๊ธฐ๊ฐ ์ฌ๋ผ๊ฐ๋ ํจ๊ณผ๋ฅผ ๋ง๋ค์์ฃ .
์ด์ SVG์ ๊ธฐ๋ณธ์ ์ดํดํ์ผ๋, ๋ ๋ณต์กํ๊ณ ์์ธํ ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ๋ง๋ค์ด ๋ณผ ์ค๋น๊ฐ ๋์์ต๋๋ค!
3. ํ์ฐ ๊ตฌ์กฐ์ ์ธ๋ถ ์์ ๊ตฌํ
ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ๋์ฑ ์ ๊ตํ๊ฒ ๋ง๋ค๊ธฐ ์ํด, ํ์ฐ์ ์ธ๋ถ ๊ตฌ์กฐ๋ฅผ SVG๋ก ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ง๊ทธ๋ง์ ์ด๋ ๊ฒฝ๋ก์ ๋ถ์ถ ๊ณผ์ ์ ๋ ์์ธํ ํํํ ์ ์์ต๋๋ค.
ํ์ฐ์ ์ฃผ์ ๊ตฌ์กฐ์ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ง๊ทธ๋ง ์ฑ๋ฒ: ์งํ ๊น์ ๊ณณ์ ์์นํ ๋ง๊ทธ๋ง ์ ์ฅ์
- ํ๋: ๋ง๊ทธ๋ง๊ฐ ์งํ๋ฉด์ผ๋ก ์์นํ๋ ํต๋ก
- ๋ถํ๊ตฌ: ํ์ฐ ์ ์๋ถ์ ๊ฐ๊ตฌ๋ถ
- ์ธกํ์ฐ: ์ฃผ ํ์ฐ์ฒด ์๋ฉด์ ํ์ฑ๋ ์์ ํ์ฐ
- ํ์ฐ์: ๋ถ์ถ๋ ๋ง๊ทธ๋ง๊ฐ ๊ตณ์ด ํ์ฑ๋ ์์
์ด์ ์ด๋ฌํ ์์๋ค์ ํฌํจํ ๋ ์์ธํ ํ์ฐ ๊ตฌ์กฐ๋ฅผ SVG๋ก ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค:
์ด SVG ๋ค์ด์ด๊ทธ๋จ์ ํ์ฐ์ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ๋์ฑ ์์ธํ๊ฒ ๋ณด์ฌ์ค๋๋ค. ์ฃผ์ ํน์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ง๊ทธ๋ง ์ฑ๋ฒ: ํ์ ํํ๋ก ํํ๋๋ฉฐ, ๋ฐํฌ๋ช ํ ๋นจ๊ฐ์์ผ๋ก ์ฑ์์ ธ ์์ต๋๋ค.
- ํ๋: ๋ง๊ทธ๋ง ์ฑ๋ฒ์์ ๋ถํ๊ตฌ๊น์ง ์ด์ด์ง๋ ๊ตต์ ์ ์ผ๋ก ํํ๋ฉ๋๋ค.
- ๋ถํ๊ตฌ: ํ์ฐ ์ ์๋ถ์ ํ์ํ ๊ฐ๊ตฌ๋ถ์ ๋๋ค.
- ์ธกํ์ฐ: ์ฃผ ํ์ฐ์ฒด ์๋ฉด์ ์์ ์ผ๊ฐํ ๋ชจ์์ผ๋ก ํํ๋์์ต๋๋ค.
- ํ์ฐ์: ํ์ฐ ์ฃผ๋ณ์ ํ์ ์์ผ๋ก ํํ๋ ์์๋ค์ ๋๋ค.
๋ํ, ์ ๋๋ฉ์ด์ ํจ๊ณผ๋ฅผ ์ถ๊ฐํ์ฌ ๋ง๊ทธ๋ง์ ์ด๋๊ณผ ๋ถ์ถ ๊ณผ์ ์ ๋์ ์ผ๋ก ํํํ์ต๋๋ค:
- ๋ง๊ทธ๋ง ์ด๋: ๋ง๊ทธ๋ง ์ฑ๋ฒ์์ ๋ถํ๊ตฌ๊น์ง ๋นจ๊ฐ ์๋ค์ด ์์นํ๋ ์ ๋๋ฉ์ด์
- ๋ถ์ถ: ๋ถํ๊ตฌ์์ ํฌ๊ธฐ๊ฐ ๋ณํ๋ ์๋ค๋ก ๋ถ์ถ ๊ณผ์ ์ ํํ
์ด๋ฌํ ์์ธํ SVG ๊ตฌํ์ ํตํด, ์ฐ๋ฆฌ๋ ํ์ฐ์ ๋ณต์กํ ๋ด๋ถ ๊ตฌ์กฐ์ ๋์ ์ธ ๋ถ์ถ ๊ณผ์ ์ ์๊ฐ์ ์ผ๋ก ๋ช ํํ๊ฒ ํํํ ์ ์๊ฒ ๋์์ต๋๋ค. ์ด๋ ์ง์งํ์ ๊ฐ๋ ์ ์ดํดํ๋ ๋ฐ ํฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
4. ์ธํฐ๋ํฐ๋ธ ์์ ์ถ๊ฐํ๊ธฐ
์ด์ ์ฐ๋ฆฌ์ ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ์ธํฐ๋ํฐ๋ธ ์์๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค. ์ฌ์ฉ์๊ฐ ์ง์ ์๋ฎฌ๋ ์ด์ ๊ณผ ์ํธ์์ฉํ ์ ์๊ฒ ๋ง๋ค๋ฉด, ํ์ต ํจ๊ณผ๊ฐ ๋์ฑ ๋์์ง ๊ฒ์ ๋๋ค. SVG์ JavaScript๋ฅผ ๊ฒฐํฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ ์ธํฐ๋ํฐ๋ธ ๊ธฐ๋ฅ์ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค:
- ๋ง๊ทธ๋ง ์๋ ฅ ์กฐ์
- ํ์ฐ ์ ํ ์ ํ
- ๋ถ์ถ ์์/์ ์ง ์ ์ด
๋จผ์ , HTML์ ํ์ํ ์ปจํธ๋กค ์์๋ค์ ์ถ๊ฐํฉ๋๋ค:
<div id="controls" style="margin: 20px 0;">
<label for="pressure">๋ง๊ทธ๋ง ์๋ ฅ: </label>
<input type="range" id="pressure" min="1" max="10" value="5">
<label for="volcanoType">ํ์ฐ ์ ํ: </label>
<select id="volcanoType">
<option value="shield">์์ํ์ฐ</option>
<option value="stratovolcano">์ฑ์ธตํ์ฐ</option>
<option value="caldera">์นผ๋ฐ๋ผ</option>
</select>
<button id="eruptButton">๋ถ์ถ ์์/์ ์ง</button>
</div>
์ด์ ์ด ์ปจํธ๋กค๋ค๊ณผ ์ฐ๋๋๋ JavaScript ์ฝ๋๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค:
// SVG ์์๋ค์ ์ ํํฉ๋๋ค
const magmaChamber = document.querySelector('#magmaChamber');
const conduit = document.querySelector('#conduit');
const crater = document.querySelector('#crater');
const eruptionParticles = document.querySelector('#eruptionParticles');
// ์ปจํธ๋กค ์์๋ค์ ์ ํํฉ๋๋ค
const pressureSlider = document.querySelector('#pressure');
const volcanoTypeSelect = document.querySelector('#volcanoType');
const eruptButton = document.querySelector('#eruptButton');
let isErupting = false;
// ๋ง๊ทธ๋ง ์๋ ฅ ์กฐ์
pressureSlider.addEventListener('input', (e) => {
const pressure = e.target.value;
magmaChamber.setAttribute('ry', 80 + pressure * 2);
conduit.setAttribute('stroke-width', 30 + pressure * 2);
});
// ํ์ฐ ์ ํ ๋ณ๊ฒฝ
volcanoTypeSelect.addEventListener('change', (e) => {
const type = e.target.value;
switch(type) {
case 'shield':
crater.setAttribute('rx', '100');
crater.setAttribute('ry', '20');
break;
case 'stratovolcano':
crater.setAttribute('rx', '50');
crater.setAttribute('ry', '20');
break;
case 'caldera':
crater.setAttribute('rx', '150');
crater.setAttribute('ry', '50');
break;
}
});
// ๋ถ์ถ ์์/์ ์ง
eruptButton.addEventListener('click', () => {
isErupting = !isErupting;
if (isErupting) {
eruptionParticles.style.display = 'block';
eruptButton.textContent = '๋ถ์ถ ์ ์ง';
} else {
eruptionParticles.style.display = 'none';
eruptButton.textContent = '๋ถ์ถ ์์';
}
});
// ๋ถ์ถ ์ ๋๋ฉ์ด์
function animateEruption() {
if (!isErupting) return;
const particle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
particle.setAttribute('cx', 400);
particle.setAttribute('cy', 100);
particle.setAttribute('r', 5);
particle.setAttribute('fill', '#FF4500');
const animX = document.createElementNS("http://www.w3.org/2000/svg", "animate");
animX.setAttribute('attributeName', 'cx');
animX.setAttribute('from', '400');
animX.setAttribute('to', 350 + Math.random() * 100);
animX.setAttribute('dur', '2s');
animX.setAttribute('fill', 'freeze');
const animY = document.createElementNS("http://www.w3.org/2000/svg", "animate");
animY.setAttribute('attributeName', 'cy');
animY.setAttribute('from', '100');
animY.setAttribute('to', '0');
animY.setAttribute('dur', '2s');
animY.setAttribute('fill', 'freeze');
const animOpacity = document.createElementNS("http://www.w3.org/2000/svg", "animate");
animOpacity.setAttribute('attributeName', 'opacity');
animOpacity.setAttribute('from', '1');
animOpacity.setAttribute('to', '0');
animOpacity.setAttribute('dur', '2s');
animOpacity.setAttribute('fill', 'freeze');
particle.appendChild(animX);
particle.appendChild(animY);
particle.appendChild(animOpacity);
eruptionParticles.appendChild(particle);
setTimeout(() => {
eruptionParticles.removeChild(particle);
}, 2000);
}
setInterval(animateEruption, 100);
์ด JavaScript ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค:
- ๋ง๊ทธ๋ง ์๋ ฅ ์ฌ๋ผ์ด๋๋ฅผ ์กฐ์ ํ๋ฉด ๋ง๊ทธ๋ง ์ฑ๋ฒ์ ํฌ๊ธฐ์ ํ๋์ ๋๋น๊ฐ ๋ณํฉ๋๋ค.
- ํ์ฐ ์ ํ์ ์ ํํ๋ฉด ๋ถํ๊ตฌ์ ๋ชจ์์ด ๋ณ๊ฒฝ๋ฉ๋๋ค.
- '๋ถ์ถ ์์/์ ์ง' ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ถ์ถ ์ ๋๋ฉ์ด์ ์ด ์์๋๊ฑฐ๋ ๋ฉ์ถฅ๋๋ค.
- ๋ถ์ถ ์ ๋๋ฉ์ด์ ์ SVG ์์๋ฅผ ๋์ ์ผ๋ก ์์ฑํ๊ณ ์ ๋๋ฉ์ด์ ์ ์ ์ฉํ์ฌ ๊ตฌํ๋ฉ๋๋ค.
์ด๋ฌํ ์ธํฐ๋ํฐ๋ธ ์์๋ค์ ์ถ๊ฐํจ์ผ๋ก์จ, ์ฌ์ฉ์๋ค์ ํ์ฐ ๋ถ์ถ ๊ณผ์ ์ ์ง์ ์กฐ์ํ๊ณ ๊ด์ฐฐํ ์ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ ๋จ์ํ ์ ์ ์ธ ์ด๋ฏธ์ง๋ ์ ๋๋ฉ์ด์ ์ ๋ณด๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ํจ๊ณผ์ ์ธ ํ์ต ๊ฒฝํ์ ์ ๊ณตํ ๊ฒ์ ๋๋ค.
์ฌ๋ฅ๋ท์์ ์ด๋ฐ ์ข ๋ฅ์ ์ธํฐ๋ํฐ๋ธ ๊ต์ก ์ฝํ ์ธ ๋ฅผ ๋ง๋๋ ์ฌ๋ฅ์ ๊ฐ์ง ๋ถ๋ค์ ์ฐพ์๋ณผ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐ์ ์ ๊ต์ก ๋ถ์ผ์์ ๋งค์ฐ ๊ฐ์น ์๊ฒ ํ์ฉ๋ ์ ์์ผ๋ฉฐ, ์ฌ ๋ฅ๋ท์ ํตํด ์ด๋ฌํ ๊ธฐ์ ์ ๊ณต์ ํ๊ณ ๋ฐ์ ์ํฌ ์ ์์ต๋๋ค.
5. ๋ฐ์ดํฐ ์๊ฐํ: ์ค์ ํ์ฐ ๋ฐ์ดํฐ ํตํฉํ๊ธฐ
์ฐ๋ฆฌ์ ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ ํ ๋จ๊ณ ๋ ๋ฐ์ ์์ผ ์ค์ ํ์ฐ ๋ฐ์ดํฐ๋ฅผ ํตํฉํด ๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ค์ ์ค์ ํ์ฐ์ ํน์ฑ์ ์ดํดํ๊ณ ๋น๊ตํ ์ ์๊ฒ ๋ ๊ฒ์ ๋๋ค. ์ฌ๊ธฐ์๋ ์ธ๊ณ์ ์ฃผ์ ํ์ฐ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์๊ฐํ๋ฅผ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ , ๊ฐ์์ ํ์ฐ ๋ฐ์ดํฐ์ ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค:
const volcanoes = [
{ name: "๋ง์ฐ๋๋ก์", type: "shield", height: 4169, lastEruption: 1984 },
{ name: "๋ฒ ์๋น์ค", type: "stratovolcano", height: 1281, lastEruption: 1944 },
{ name: "ํฌ๋ผ์นดํ์ฐ", type: "caldera", height: 813, lastEruption: 2018 },
{ name: "ํ์ง์ฐ", type: "stratovolcano", height: 3776, lastEruption: 1707 },
{ name: "์๋ก์คํค", type: "caldera", height: 2805, lastEruption: -70000 }
];
์ด์ ์ด ๋ฐ์ดํฐ๋ฅผ ์๊ฐํํ๋ ํจ์๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค:
function createVolcanoChart() {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("width", "800");
svg.setAttribute("height", "400");
svg.setAttribute("viewBox", "0 0 800 400");
const maxHeight = Math.max(...volcanoes.map(v => v.height));
volcanoes.forEach((volcano, index) => {
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
// ํ์ฐ ๋ชจ์ ๊ทธ๋ฆฌ๊ธฐ
const volcanoShape = document.createElementNS("http://www.w3.org/2000/svg", "path");
const height = (volcano.height / maxHeight) * 300;
let d;
switch(volcano.type) {
case "shield":
d = `M${150*index+50},350 Q${150*index+125},${350-height} ${150*index+200},350`;
break;
case "stratovolcano":
d = `M${150*index+75},350 L${150*index+125},${350-height} L${150*index+175},350`;
break;
case "caldera":
d = `M${150*index+50},350 L${150*index+75},${350-height} L${150*index+175},${350-height} L${150*index+200},350`;
break;
}
volcanoShape.setAttribute("d", d);
volcanoShape.setAttribute("fill", "#A52A2A");
// ํ์ฐ ์ด๋ฆ ํ์
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.setAttribute("x", 150*index+100);
text.setAttribute("y", 380);
text.setAttribute("text-anchor", "middle");
text.textContent = volcano.name;
group.appendChild(volcanoShape);
group.appendChild(text);
svg.appendChild(group);
});
document.body.appendChild(svg);
}
createVolcanoChart();
์ด ํจ์๋ ๊ฐ ํ์ฐ์ ์ ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ชจ์์ผ๋ก ํ์ฐ์ ๊ทธ๋ฆฌ๊ณ , ๋์ด์ ๋น๋กํ์ฌ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํฉ๋๋ค. ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ ์ฐจํธ๊ฐ ๋ ๊ฒ์ ๋๋ค:
์ด ์ฐจํธ๋ฅผ ํตํด ์ฌ์ฉ์๋ค์ ๋ค์ํ ํ์ฐ์ ์ ํ๊ณผ ์๋์ ์ธ ํฌ๊ธฐ๋ฅผ ํ๋์ ๋น๊ตํ ์ ์์ต๋๋ค. ์ถ๊ฐ์ ์ผ๋ก, ๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ๋ฅผ ํตํด ๊ฐ ํ์ฐ์ ์์ธ ์ ๋ณด๋ฅผ ํ์ํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ์๋ ์์ต๋๋ค.
6. ์ฑ๋ฅ ์ต์ ํ ๋ฐ ์ ๊ทผ์ฑ ๊ณ ๋ ค
์ฐ๋ฆฌ์ ํ์ฐ ๋ถ์ถ ์๋ฎฌ๋ ์ด์ ์ด ๋์ฑ ๋ณต์กํด์ง์ ๋ฐ๋ผ, ์ฑ๋ฅ ์ต์ ํ์ ์ ๊ทผ์ฑ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ๋ค์์ ์ด๋ฅผ ์ํ ๋ช ๊ฐ์ง ํ์ ๋๋ค:
- SVG ์ต์ ํ: ๋ถํ์ํ ๊ฒฝ๋ก์ ์ ์ ๊ฑฐํ๊ณ , ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ๋ํ์ ์ฌ์ฉํฉ๋๋ค.
- ์ ๋๋ฉ์ด์ ์ต์ ํ: requestAnimationFrame์ ์ฌ์ฉํ์ฌ ๋ถ๋๋ฌ์ด ์ ๋๋ฉ์ด์ ์ ๊ตฌํํฉ๋๋ค.
- ๋ ์ด์ด ์ฌ์ฉ: ๋ณต์กํ ์์๋ค์ ๋ณ๋์ ๋ ์ด์ด๋ก ๋ถ๋ฆฌํ์ฌ ๋ ๋๋ง ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ์ ๊ทผ์ฑ ํฅ์: ARIA ์์ฑ์ ์ฌ์ฉํ์ฌ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๋ค๋ ์ฝํ ์ธ ๋ฅผ ์ดํดํ ์ ์๊ฒ ํฉ๋๋ค.
- ๋ฐ์ํ ๋์์ธ: viewBox ์์ฑ์ ํ์ฉํ์ฌ ๋ค์ํ ํ๋ฉด ํฌ๊ธฐ์ ๋์ํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์ ๊ทผ์ฑ์ ๊ณ ๋ คํ SVG ์์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค: