Javascript
[Javascript] 이미지맵 반응형에서 적용하기 (rect, circle, poly 모두 지원)
- 2025.08.14 13:46:58
![]() pc기준으로 이미지맵을 적용한 경우 반응형에서 줄어든 이미지의 비율에 따라 자동으로 이미지맵 좌표를 수정해준다. (rect, circle, poly 모두 지원) 단, 이미지는 max-width: 100%; height: aut; 처리 되어 있어야 한다. [!]javascript[/!] 아래와 같이 구현한다. <style>
/* 반응형 기본 */ img[usemap] { max-width: 100%; height: auto; display:block; } </style> <script> // 반응형 이미지맵 스케일러 (() => { const imgs = Array.from(document.querySelectorAll('img[usemap]')); const parseNums = s => s.split(',').map(n => parseFloat(n.trim())); const storeOriginalCoords = map => { map.querySelectorAll('area').forEach(a => { if (!a.dataset.origCoords) a.dataset.origCoords = a.coords; }); }; const scaleArea = (area, rw, rh) => { const shape = (area.shape || 'rect').toLowerCase(); const orig = parseNums(area.dataset.origCoords); if (shape === 'rect') { // x1,y1,x2,y2 const [x1,y1,x2,y2] = orig; area.coords = [ Math.round(x1 * rw), Math.round(y1 * rh), Math.round(x2 * rw), Math.round(y2 * rh) ].join(','); } else if (shape === 'circle') { // x,y,r const [x,y,r] = orig; const rScaled = Math.round(r * (rw + rh) / 2); area.coords = [ Math.round(x * rw), Math.round(y * rh), rScaled ].join(','); } else if (shape === 'poly') { // x1,y1,x2,y2, ... const scaled = orig.map((v, i) => Math.round(v * (i % 2 ? rh : rw))); area.coords = scaled.join(','); } }; const resizeMapForImage = img => { const usemap = img.getAttribute('usemap'); if (!usemap) return; // 연결된 <map> 찾기 const name = usemap.replace('#',''); const map = document.querySelector(`map[name="${name}"], map#${name}`); if (!map) return; // 원본 좌표 저장 storeOriginalCoords(map); // 이미지 실제 크기/표시 크기 const naturalW = img.naturalWidth || img.width; const naturalH = img.naturalHeight || img.height; const displayW = img.clientWidth; const displayH = img.clientHeight || Math.round(displayW * (naturalH / naturalW)); if (!naturalW || !naturalH || !displayW || !displayH) return; const rw = displayW / naturalW; const rh = displayH / naturalH; map.querySelectorAll('area').forEach(a => scaleArea(a, rw, rh)); }; // 디바운스 리사이즈 let rid; const onResize = () => { cancelAnimationFrame(rid); rid = requestAnimationFrame(() => imgs.forEach(resizeMapForImage)); }; // 초기 바인딩 imgs.forEach(img => { if (img.complete && img.naturalWidth) { resizeMapForImage(img); } else { img.addEventListener('load', () => resizeMapForImage(img), { once:true }); } }); window.addEventListener('resize', onResize); window.addEventListener('orientationchange', onResize); })(); </script> |