인터랙티브 테이블 + 스크롤 기반 데이터 기사 · 코드 그대로 복사 → 데이터만 교체
$('#table').DataTable({...})new IntersectionObserver(callback, options)scrollama().setup({step}).onStepEnter(...)// ── 스크롤리텔링의 핵심 패턴 ── // 1) 차트 영역(왼쪽)을 sticky로 화면에 고정 // 2) 텍스트(오른쪽)를 스크롤하며 단계 진입 시 차트만 갱신 const scroller = scrollama(); scroller .setup({ step: '.scroll-step', offset: 0.5 }) // step이 화면 50% 지점에 오면 발동 .onStepEnter(({ element, index }) => { document.querySelectorAll('.scroll-step') .forEach(s => s.classList.remove('is-active')); element.classList.add('is-active'); showStage(index); // 차트 전환 함수 }); window.addEventListener('resize', scroller.resize);
"수십 행짜리 표"를 독자가 직접 정렬·검색·페이지 이동할 수 있게 만드는 방법.
기존 HTML <table>에 한 줄만 적용하면 즉시 인터랙티브 테이블로 변신합니다.
<table id="..."> 그대로 두고 $('#id').DataTable(...) 한 줄. 행은 <tbody>에 평범하게.// ① CDN: jQuery + DataTables (CSS도 추가) // <link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/jquery.dataTables.min.css"/> // <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script> // <script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script> // ② 일반 HTML 테이블 — 행만 자기 데이터로 교체 // <table id="myTable"> // <thead><tr><th>시도</th><th>사고건수</th><th>사망률</th></tr></thead> // <tbody> // <tr><td>서울</td><td>34215</td><td>0.74</td></tr> // ... // </tbody> // </table> // ③ JS 한 줄로 활성화 $(document).ready(function() { $('#myTable').DataTable({ language: { // 한글화 search: '검색:', lengthMenu: '_MENU_ 개씩 보기', info: '_START_–_END_ / _TOTAL_ 개', paginate: { previous: '이전', next: '다음' } }, order: [[1, 'desc']], // 초기 정렬: 1번 열, 내림차순 pageLength: 7 // 페이지당 행 수 }); }); // ── fetch로 데이터 동적 로드 (실무) ── // fetch('data.json').then(r => r.json()).then(rows => { // const tbody = document.querySelector('#myTable tbody'); // tbody.innerHTML = rows.map(r => // `<tr><td>${r.시도}</td><td>${r.사고건수}</td><td>${r.사망률}</td></tr>`).join(''); // $('#myTable').DataTable({...}); // });
🔍 해보기: 헤더 클릭으로 정렬, 검색창에 시도명 입력.
| 시도 | 사고건수 | 사망자 | 부상자 | 사망률(%) | 10만명당 |
|---|---|---|---|---|---|
| 서울 | 34215 | 252 | 49821 | 0.736 | 35.2 |
| 경기 | 58432 | 681 | 87234 | 1.165 | 43.8 |
| 부산 | 15621 | 178 | 22341 | 1.139 | 47.2 |
| 대구 | 9843 | 98 | 14521 | 0.996 | 41.3 |
| 인천 | 14523 | 141 | 21234 | 0.971 | 48.1 |
| 광주 | 7234 | 67 | 10821 | 0.926 | 50.3 |
| 대전 | 8123 | 83 | 12341 | 1.022 | 55.7 |
| 울산 | 5234 | 52 | 7823 | 0.994 | 45.2 |
| 세종 | 1893 | 18 | 2834 | 0.951 | 52.4 |
| 강원 | 7891 | 156 | 10234 | 1.977 | 51.6 |
| 충북 | 8234 | 143 | 11234 | 1.737 | 52.3 |
| 충남 | 11234 | 198 | 15234 | 1.763 | 53.5 |
| 전북 | 9123 | 145 | 12234 | 1.590 | 51.2 |
| 전남 | 10234 | 187 | 13234 | 1.828 | 56.1 |
| 경북 | 13234 | 243 | 17234 | 1.836 | 50.8 |
| 경남 | 17234 | 254 | 24234 | 1.474 | 51.7 |
| 제주 | 4823 | 52 | 6823 | 1.078 | 72.1 |
스크롤 기반 시각화의 기초 원리를 직접 눈으로 확인. 이 기술 위에 ③ Scrollama가 만들어졌고, ④ 완성 기사가 동작합니다.
scroll 이벤트보다 성능이 좋아 표준화됨.root)가 자체 스크롤되면 root: containerEl 명시 필요.root (감지 기준 컨테이너, null=뷰포트) ② threshold (몇 % 보일 때 발동) ③ 콜백.// ① CDN 불필요 ─── 브라우저 기본 API // ② 감시할 요소들과 컨테이너 준비 // <div id="container"> // <div class="item">...</div> (여러 개) // </div> // ③ Observer 생성 const observer = new IntersectionObserver( entries => { // 콜백: entries는 변화 있는 요소들 entries.forEach(e => { e.target.classList.toggle('visible', e.isIntersecting); // e.isIntersecting === true → 화면에 들어옴 }); }, { root: document.getElementById('container'), // null이면 브라우저 뷰포트 threshold: 0.5 // 50% 이상 보일 때 발동 } ); // ④ 감시할 요소들 등록 document.querySelectorAll('.item').forEach(el => observer.observe(el));
▼ 아래 박스를 스크롤해 보세요. 화면 안에 들어오면 보라색으로 변합니다.
NYT·워싱턴포스트·SBS·한겨레 등이 쓰는 "스크롤리텔링"의 핵심 패턴.
왼쪽 차트를 화면에 고정(sticky)해 두고, 오른쪽 텍스트를 스크롤하면 단계마다 차트가 바뀝니다.
onStepEnter 콜백에서 차트만 바꿈.scrollama().setup({step}) + onStepEnter에서 차트 갱신 함수 호출.// ① CDN: Scrollama + Chart.js // <script src="https://cdn.jsdelivr.net/npm/scrollama@3.2.0/build/scrollama.min.js"></script> // <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script> // ② HTML 구조 ─── sticky 차트 + 텍스트 step들 // <div class="scroll-demo"> // <div class="sticky-stage"><canvas id="stage-canvas"></canvas></div> // <div class="scroll-steps"> // <div class="scroll-step">...텍스트 1...</div> // <div class="scroll-step">...텍스트 2...</div> // </div> // </div> // ③ 데이터 + 단계별 차트 빌더 함수 const years = [2016,2017,2018,2019,2020,2021,2022,2023]; const 사고건수 = [220917,216335,217148,229600,209654,203130,196836,191418]; const 유형 = ['차대차','차대사람','차량단독','기타']; const 유형건수 = [142350, 42580, 6380, 108]; let chart = null; function showStage(idx) { if (chart) chart.destroy(); // 매번 destroy → 재생성 const canvas = document.getElementById('stage-canvas'); if (idx === 0) { // 단계별로 다른 차트 chart = new Chart(canvas, { type:'line', data:{ labels: years, datasets:[{ label:'사고건수', data: 사고건수, borderColor:'#7c3aed' }] } }); } else if (idx === 1) { const minIdx = 사고건수.indexOf(Math.min(...사고건수.slice(3,6))); const colors = 사고건수.map((_,i) => i===minIdx ? '#ef4444' : 'rgba(124,58,237,0.35)'); chart = new Chart(canvas, { type:'bar', data:{ labels: years, datasets:[{ data: 사고건수, backgroundColor: colors }] } }); } else if (idx === 2) { chart = new Chart(canvas, { type:'doughnut', data:{ labels: 유형, datasets:[{ data: 유형건수 }] } }); } // ... 단계만큼 추가 } showStage(0); // 첫 진입 시 // ④ Scrollama 연결 ─── step이 화면 50% 지점에 오면 발동 const scroller = scrollama(); scroller .setup({ step: '.scroll-step', offset: 0.5 }) .onStepEnter(({ element, index }) => { document.querySelectorAll('.scroll-step') .forEach(s => s.classList.remove('is-active')); element.classList.add('is-active'); showStage(index); // 차트 전환 }); window.addEventListener('resize', scroller.resize);
한 해 정점(약 23만 건)을 찍은 뒤 꾸준히 감소해 최근 19만 건대까지 떨어졌습니다.
특정 한 해는 이동량 감소로 직전 해 대비 약 9% 급감했습니다(코로나19 시기).
전체 사고의 74%가 차대차 사고입니다. 그러나 사망 비율은 차대사람이 35%로 가장 높습니다.
경기·서울·경남·부산 4개 시도가 전체 사고의 절반 이상을 차지합니다.
여전히 하루 평균 7명이 교통사고로 목숨을 잃고 있습니다.
지금까지 배운 모든 것(차트 + 스크롤 감지 + sticky 레이아웃)을 합쳐 만든
실제 신문 기사 형태의 5섹션 인터랙티브 기사.
탭이 아닌 전체 화면에서 sticky·스크롤이 자연스럽게 동작하므로 새 창으로 엽니다.
position:sticky로 차트 영역이 화면 절반을 고정. 오른쪽 텍스트가 흐르며 차트가 단계 전환.document.write를 막을 수 있음 → 그땐 별도 .html로 저장 후 직접 여세요.article.html로 저장 → Live Server에서 열기. ③ Scrollama 패턴이 실제 페이지에서 작동하는 환경이 됨.// ── 새 창에 HTML 통째로 작성하는 패턴 (개발용) ── function openArticle() { const html = `<!DOCTYPE html> <html><head> <title>교통사고 — 데이터로 보는 1년</title> <script src="https://cdn.jsdelivr.net/npm/scrollama@3.2.0/build/scrollama.min.js"><\/script> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"><\/script> <style> .sticky-stage { position: sticky; top: 0; height: 100vh; ... } .step { min-height: 90vh; ... } </style> </head><body> <div class="hero">...</div> <div class="scroll-section"> <div class="sticky-stage"><canvas id="art-canvas"></canvas></div> <div class="steps"> <div class="step" data-step="0">...</div> ... 5단계 ... </div> </div> <script> function showStep(s) { ... 차트 갱신 ... } showStep(0); scrollama().setup({step:'.step',offset:0.5}) .onStepEnter(({index}) => showStep(index)); <\/script> </body></html>`; const w = window.open('', '_blank'); w.document.write(html); w.document.close(); } // ── 실무 권장 ── // article.html 파일로 저장하고 Live Server 등으로 직접 열기. // 그 쪽이 디버깅·캐싱·SEO 모두 유리.
article.html로 저장하고 Live Server에서 열면 됩니다.