μ§ν μν©μ μκ°ννλ νμλΌμΈ UI λ§λ€κΈ° (JavaScript κΈ°λ°)
μΉμμ μ¬μ©μμ μμΉμ μ§ν μνλ₯Ό λͺ ννκ² λ³΄μ¬μ£Όλ UIλ μ¬μ©μ κ²½νμ ν° μν₯μ μ€λλ€. νΉν CADμ κ°μ κΈ°μ μλ£λ₯Ό μ 곡νλ νμ΄μ§μμλ “μ§κΈ λ΄κ° μ΄λ€ λ¨κ³μ μλμ§”λ₯Ό μ§κ΄μ μΌλ‘ μΈμν μ μμ΄μΌ νμ£ . μ΄λ² κΈμμλ JavaScriptμ CSSλ§μΌλ‘ ꡬννλ μ§ν λ¨κ³ νμλΌμΈ UIλ₯Ό μκ°ν©λλ€.
π‘ μ§μ νμ©ν μμλ νμ¬ CAD νμ΄μ§μ νλ¦
STEP 1: CAD νμΌ μ€λΉ >> STEP 2: CAD νμΌ κ²ν >> STEP 3: μΉμΈ λκΈ° >> STEP 4: λ€μ΄λ‘λ κ°λ₯ |
STEP 1κ³Ό STEP 2λ μ΄λ―Έμ§κ° μ΄λ―Έ λ±λ‘λ μλ£ λ¨κ³λ‘ κ°μ μμμΌλ‘ κ·Έλ£Ήννκ³ , μΉμΈ λκΈ° μνμΈ STEP 3λ κ°μ‘° μ λλ©μ΄μ μΌλ‘ ννν΄ μ¬μ©μμ μ£Όμλ₯Ό λ μ μλλ‘ κ΅¬μ±ν΄ λ΄€μ΅λλ€.
β μ£Όμ κΈ°λ₯ μμ½
- μ€ν 1, μ€ν 2λ λμΌν μμμΌλ‘ κ·Έλ£Ήν (μ: μλ£λ λ¨κ³)
- νμ¬ μ§ν μ€μΈ μ€ν μ κ°μ‘° μ λλ©μ΄μ μ μ©
- λ§μ°μ€ μ€λ² μ ν΄νμΌλ‘ μμΈ μ€λͺ μ 곡
- λ°μν λμμΈμΌλ‘ λͺ¨λ°μΌ λμ
π§© HTML ꡬ쑰 μμ
<div class="timeline">
<div class="step completed">STEP 1<br><span>CAD νμΌ μ€λΉ</span></div>
<div class="step completed">STEP 2<br><span>CAD νμΌ κ²ν </span></div>
<div class="step active">STEP 3<br><span>μΉμΈ λκΈ°</span></div>
<div class="step">STEP 4<br><span>λ€μ΄λ‘λ κ°λ₯</span></div>
</div>
π¨ CSS λμμΈ ν¬μΈνΈ
.timeline {
display: flex;
justify-content: space-between;
margin: 30px 0;
}
.step {
flex: 1;
text-align: center;
padding: 10px;
border-bottom: 4px solid #ccc;
position: relative;
}
.step.completed {
border-color: #4CAF50; /* μλ£λ μ€ν
μμ */
color: #4CAF50;
}
.step.active {
border-color: #FF9800;
color: #FF9800;
animation: pulse 1s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.6; }
100% { opacity: 1; }
}
π‘ νμ© μμ: CAD λ°μ΄ν° λ€μ΄λ‘λ νλ¦
- STEP 1~2: μ΄λ―Έμ§κ° μ΄λ―Έ λ±λ‘λ μν → κ°μ μμμΌλ‘ κ·Έλ£Ή μ²λ¦¬
- STEP 3: μΉμΈ λκΈ° μν → κ°μ‘° μ λλ©μ΄μ
- STEP 4: λ€μ΄λ‘λ κ°λ₯ → νμ μ²λ¦¬
μ΄λ° λ°©μμΌλ‘ μ€μ 3D CAD λ°μ΄ν° νμ΄μ§μ νλ¦μ μκ°ννλ©΄, μ¬μ©μμκ² νμ¬ μμΉλ₯Ό λͺ νν μ λ¬ν μ μμ΄μ.
μλ°μ€ν¬λ¦½νΈλ‘ ꡬννλ μΈν°λν°λΈ νμλΌμΈ UI – CAD νμ΄μ§ νλ¦μ μ μ©νκΈ°
κΈ°μ‘΄μλ μ μ μΈ νμλΌμΈ UIλ₯Ό HTMLκ³Ό CSSλ§μΌλ‘ ꡬμ±νμ§λ§, μ΄λ²μλ μ¬μ©μμ μνΈμμ©μ λ°λΌ μ§ν λ¨κ³λ₯Ό μ μ΄νκ±°λ μ λλ©μ΄μ μ μ μ΄ν μ μλ λμ νμλΌμΈμΌλ‘ νμ₯ν΄ λ΄ λλ€.
β JavaScript μ½λ μμ
// μ΄κΈ° μν κ°μ Έμ€κΈ°
let currentStep = parseInt(localStorage.getItem('currentStep')) || 1;
const steps = document.querySelectorAll('.step');
function renderSteps(step) {
steps.forEach((el, i) => {
el.classList.remove('completed', 'active');
if (i < step - 1) el.classList.add('completed'); // μ΄μ λ¨κ³
else if (i === step - 1) el.classList.add('active'); // νμ¬ λ¨κ³
});
}
renderSteps(currentStep);
// ν΄λ¦ μ΄λ²€νΈλ‘ λ¨κ³ μ΄λ
steps.forEach((el, i) => {
el.addEventListener('click', () => {
currentStep = i + 1;
localStorage.setItem('currentStep', currentStep);
renderSteps(currentStep);
});
});
μ΄ μ½λλ μ¬μ©μ ν΄λ¦μΌλ‘ μ§ν λ¨κ³λ₯Ό μ λ°μ΄νΈνκ³ , λ€μ λ°©λ¬Έ μμλ μ΄μ μνλ₯Ό μ μ§ν μ μκ² ν΄μ€λλ€.
π‘ μ μ© μμ΄λμ΄: ν΄λ¦μΌλ‘ λ¨κ³ μ ν + μ μ₯ κΈ°λ₯
- μ¬μ©μκ° STEP 1~4 μ€ νλλ₯Ό ν΄λ¦νλ©΄ ν΄λΉ λ¨κ³λ‘ μ§ν μν μ λ°μ΄νΈ
- μ§ν μνλ localStorageμ μ μ₯λΌ λ€μ μ μ μμλ μ μ§
- νΉμ 쑰건(API μλ΅ λ±)μ λ°λΌ μλμΌλ‘ λ¨κ³ μ ν κ°λ₯
β νμλΌμΈ UIμ ν΅μ¬ κΈ°λ₯
- μλ£λ λ¨κ³(STEP 1~2)λ λμΌν μμκ³Ό μμ΄μ½μΌλ‘ κ·Έλ£Ή μ²λ¦¬
- μ§ν μ€μΈ λ¨κ³(STEP 3)λ μ»¬λ¬ κ°μ‘° + μ λλ©μ΄μ ν¨κ³Ό
- λκΈ° μν(STEP 4)λ νλ¦° μμΌλ‘ μκ°μ λλΉ
- λ°μν λ μ΄μμμΌλ‘ λͺ¨λ°μΌμμλ μ μλ
- μ€ν¬λ¦°λ¦¬λ μ¬μ©μλ₯Ό μν μ κ·Όμ± μμ±(aria-label, role) ν¬ν¨
π μ κ·Όμ±μ κ³ λ €ν μ€κ³ ν¬μΈνΈ
μμ¦μ λ¨μν μκ°μ λ§μ‘±μ λμ΄μ, λͺ¨λ μ¬μ©μμκ² μ 보λ₯Ό λλ±νκ² μ λ¬νλ κ²μ΄ μ€μν©λλ€.
μ΄ νμλΌμΈ μ»΄ν¬λνΈμλ λ€μκ³Ό κ°μ μ κ·Όμ± μμλ₯Ό λ°μνμ΅λλ€:
- κ° λ¨κ³μ role="listitem"κ³Ό aria-label μ μ©: μ€ν¬λ¦°λ¦¬λκ° κ° μνλ₯Ό μ½μ μ μκ² ν¨
- μμ μΈμ β/β³ λ±μ ν μ€νΈ νΉμ μμ΄μ½μΌλ‘ μν ꡬλΆ
- μΆ©λΆν μ λλΉ ν보 (WCAG κΈ°μ€ 4.5:1 μ΄μ)
- ν₯νμλ ν€λ³΄λ μ κ·Όμ±(tab ν€ μ§μ)λ μΆκ°ν κ³ν
β μ κ·Όμ± κ³ λ € HTML μμ
<section aria-labelledby="timeline-heading">
<h2 id="timeline-heading">μ§ν λ¨κ³ νμλΌμΈ</h2>
<ol class="timeline" role="list" aria-label="CAD νμΌ λ€μ΄λ‘λ μ§ν λ¨κ³">
<li class="step completed" role="listitem" aria-label="STEP 1 μλ£: CAD νμΌ μ€λΉ">
<span class="visually-hidden">β</span>
<strong>STEP 1</strong>: CAD νμΌ μ€λΉ
</li>
<li class="step completed" role="listitem" aria-label="STEP 2 μλ£: CAD νμΌ κ²ν ">
<span class="visually-hidden">β</span>
<strong>STEP 2</strong>: CAD νμΌ κ²ν
</li>
<li class="step active" role="listitem" aria-label="STEP 3 μ§νμ€: μΉμΈ λκΈ°">
<span class="visually-hidden">β³</span>
<strong>STEP 3</strong>: μΉμΈ λκΈ°
</li>
<li class="step" role="listitem" aria-label="STEP 4 μμ : λ€μ΄λ‘λ κ°λ₯">
<span class="visually-hidden">β¬</span>
<strong>STEP 4</strong>: λ€μ΄λ‘λ κ°λ₯
</li>
</ol>
</section>
π μ£Όμ μ κ·Όμ± ν¬μΈνΈ
- <ol> νκ·Έ μ¬μ© → λ¨κ³μ μμλ₯Ό μλ―Έμ μΌλ‘ νν
- aria-label, role="list" / listitem" μμ± → μ€ν¬λ¦°λ¦¬λκ° κ° λ¨κ³λ₯Ό μ νν μλ΄
- μν μμ΄μ½(β, β³, β¬) ν μ€νΈ μ¨κΉ μ²λ¦¬ → <span class="visually-hidden">μΌλ‘ μκ° μ₯μ μ¬μ©μμκ² μ€λͺ μ 곡
- aria-labelledbyλ₯Ό ν΅ν΄ νμλΌμΈ μ λͺ© μ°κ²°
π‘ μκ°μ μΌλ‘ μ¨κΈ΄ ν μ€νΈ μ²λ¦¬ CSS μμ
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
border: 0;
}
μ΄λ κ² κ΅¬μ±νλ©΄ λμμΈμ ν΄μΉμ§ μμΌλ©΄μλ 보쑰 κΈ°μ μ μ¬μ©νλ λΆλ€μκ² μΉμ ν UIκ° λ©λλ€. π
π§π» μλλ¦¬μ€ μ μ© μ (CAD λ€μ΄λ‘λ νμ΄μ§)
- μ¬μ©μκ° STEP 2(CAD μ΄λ―Έμ§ μ λ‘λ)λ₯Ό μλ£νλ©΄ μλμΌλ‘ STEP 3μΌλ‘ λμ΄κ°
- κ΄λ¦¬μ κ³μ μμλ μΉμΈ μ μλ STEP 4λ‘ μ ν + λ€μ΄λ‘λ λ²νΌ νμ±ν
- μ΄λ―Έμ§λ₯Ό μ λ‘λνλμ§ μ¬λΆλ API μνκ°μ ν΅ν΄ κ°μ§ κ°λ₯
π μΆκ° κΈ°λ₯ μμ΄λμ΄ (νμ₯ κ°λ₯)
- λ²νΌ ν΄λ¦ μ μλ²μ μν μ λ°μ΄νΈ μμ² (fetch μ΄μ©)
- μ κ·Ό μ μ΄: λ‘κ·ΈμΈν μ¬μ©μλ§ νΉμ λ¨κ³ μ§ν κ°λ₯
- μνλ³λ‘ μκ° κΈ°λ‘ μ μ₯ (μ: μΉμΈ λκΈ° μκ°μ΄ μ€λ 걸릴 κ²½μ° νμ)
π λ§λ¬΄λ¦¬νλ©°
μ΄μ²λΌ κ°λ¨ν νμλΌμΈ μ»΄ν¬λνΈ νλλ§μΌλ‘λ μ¬μ©μμ κ²½νμ νμΈ΅ λμΌ μ μμ΅λλ€.
νΉν CADμ κ°μ΄ λ¨κ³λ³ νλ¦μ΄ λͺ νν μλΉμ€λΌλ©΄ λμ± μ ν©νμ£ .
κ·Έλ¦¬κ³ JavaScriptλ₯Ό λνλ©΄ λ¨μν “λ³΄μ¬μ£Όλ UI”λ₯Ό λμ΄μ
μ¬μ©μμμ μνΈμμ©μ κΈ°λ°μΌλ‘ λ¨κ³κ° λ³κ²½λλ μ€μκ° μΈν°νμ΄μ€λ₯Ό λ§λ€ μ μμ΄μ.