ESG 스크롤 복귀와 기술 역량 이미지 정렬·지도 표시 개선
- ESG 푸터에서 위로 스크롤하면 문서 영역이 먼저 복귀하도록 처리 - 섹션 전환 중 문서 내부 스크롤을 막아 상단 잘림 방지 - 기술 역량 이미지의 상단 여백과 가용 높이를 본문 기준으로 정렬 - 이미지 진입 애니메이션을 고려해 텍스트 겹침과 화면 이탈 방지 - 기술 역량 프로젝트 순서·설명 및 개별 이미지 배치 설정 정리 - 기술 역량 데이터에 맞춰 검색용 정적 HTML 동기화 - 지도 검색용 도로명 주소와 층·호수 안내를 분리해 건물 위치 핀 표시 - 지도 기본 확대 수준을 16으로 설정하고 한국어 표시 적용 - 회사 소개·조직도와 개인정보 동의 거부 안내 문구 정리 검증: - JavaScript 구문 검사 및 git diff --check 통과 - ESG 세 문서의 푸터 복귀·내부 스크롤·키보드 이동 확인 - 기술 역량 29개 슬라이드의 데스크톱 이미지 정렬 및 모바일 이동 확인 - 본사·지사 지도 위치 핀, 상세 주소, 외부 지도 링크 확인
This commit is contained in:
37
js/main.js
37
js/main.js
@@ -176,6 +176,10 @@
|
||||
function canScrollPolicy(target, direction) {
|
||||
const panel = target.closest(".esg-policy-panel");
|
||||
if (!panel || panel.hidden) return false;
|
||||
const workspace = panel.closest(".esg-workspace");
|
||||
// Restore the whole reader below the header before scrolling its document.
|
||||
if (workspace && Math.abs(window.scrollY - sectionStop(workspace)) > 4) return false;
|
||||
if (performance.now() < transitionUntil) return false;
|
||||
const remaining = panel.scrollHeight - panel.clientHeight - panel.scrollTop;
|
||||
return direction > 0 ? remaining > 2 : panel.scrollTop > 2;
|
||||
}
|
||||
@@ -238,10 +242,8 @@
|
||||
<p>수집된 개인정보는 문의 처리 완료 후 1년간 보관하며, 보유 기간이 지나면 지체 없이 파기합니다.</p>
|
||||
<h3>4. 정보 제공 및 처리 위탁</h3>
|
||||
<p>제공된 정보는 문의 응대 목적으로 사용합니다. 외부 서비스에 처리를 위탁하는 경우 해당 서비스와 처리 범위를 운영 방침에 명시합니다.</p>
|
||||
<h3>5. 동의 거부 및 정보 확인</h3>
|
||||
<p>개인정보 수집 및 이용에 동의하지 않을 수 있습니다. 동의하지 않으면 온라인 문의를 전송할 수 없으며, 고객센터로 직접 연락할 수 있습니다. 제공한 정보의 확인, 수정, 삭제 요청도 고객센터로 문의할 수 있습니다.</p>
|
||||
<h3>6. 개인정보 관련 문의</h3>
|
||||
<p>주식회사 모비핀테크놀러지 · 고객센터 <a href="tel:0532140592">053-214-0592</a><br />평일 09:00 ~ 18:00</p>`,
|
||||
<h3>5. 동의 거부</h3>
|
||||
<p>개인정보 수집 및 이용에 동의하지 않을 수 있습니다. 다만, 동의하지 않을 경우 온라인 문의 서비스를 이용할 수 없습니다.</p>`,
|
||||
},
|
||||
sitemap: {
|
||||
title: "사이트맵",
|
||||
@@ -350,10 +352,11 @@
|
||||
trigger.addEventListener("click", () => {
|
||||
const office = trigger.dataset.mapTitle;
|
||||
const address = trigger.dataset.mapAddress;
|
||||
const query = encodeURIComponent(address);
|
||||
// Search for the building; floor/unit details can prevent a map pin from resolving.
|
||||
const query = encodeURIComponent(trigger.dataset.mapQuery || address);
|
||||
title.textContent = `${office} 오시는 길`;
|
||||
frame.title = `${office} 위치 지도`;
|
||||
frame.src = `https://maps.google.com/maps?q=${query}&z=15&output=embed`;
|
||||
frame.src = `https://maps.google.com/maps?q=${query}&z=16&hl=ko&output=embed`;
|
||||
addressLabel.textContent = address;
|
||||
mapLink.href = `https://www.google.com/maps/search/?api=1&query=${query}`;
|
||||
dialog.showModal();
|
||||
@@ -752,29 +755,43 @@
|
||||
const titleBottom = featureTitle.getBoundingClientRect().bottom - stageBounds.top;
|
||||
capabilitiesWorkbench.style.setProperty("--certificate-top", `${titleBottom + 24}px`);
|
||||
}
|
||||
const contentRight = featureContent.getBoundingClientRect().right + 32;
|
||||
const contentBounds = featureContent.getBoundingClientRect();
|
||||
const contentRight = contentBounds.right + 32;
|
||||
const contentTop = contentBounds.top;
|
||||
const contentBottom = stageBounds.bottom - parseFloat(window.getComputedStyle(stage).paddingBottom);
|
||||
[featureObject, featureObjectSecondary].forEach((element) => {
|
||||
if (!element) return;
|
||||
element.style.removeProperty("width");
|
||||
element.style.removeProperty("height");
|
||||
element.style.removeProperty("--object-fit-x");
|
||||
element.style.removeProperty("--object-fit-y");
|
||||
if (!desktop || !hasDescription || !element.getAttribute("src")) return;
|
||||
const style = window.getComputedStyle(element);
|
||||
const width = parseFloat(style.width);
|
||||
const height = parseFloat(style.height);
|
||||
const available = Math.max(0, stageBounds.right - contentRight);
|
||||
const availableHeight = Math.max(0, contentBottom - contentTop);
|
||||
if (!width || !height) return;
|
||||
// Fit the actual image ratio, not the potentially letterboxed CSS rectangle.
|
||||
const naturalWidth = element.naturalWidth;
|
||||
const naturalHeight = element.naturalHeight;
|
||||
if (!naturalWidth || !naturalHeight) return;
|
||||
const ratio = Math.min(width / naturalWidth, height / naturalHeight, available / naturalWidth);
|
||||
const ratio = Math.min(width / naturalWidth, height / naturalHeight,
|
||||
available / naturalWidth, availableHeight / naturalHeight);
|
||||
element.style.width = `${naturalWidth * ratio}px`;
|
||||
element.style.height = `${naturalHeight * ratio}px`;
|
||||
const bounds = element.getBoundingClientRect();
|
||||
const motionX = parseFloat(window.getComputedStyle(element).translate) || 0;
|
||||
const settledLeft = bounds.left - motionX;
|
||||
const fittedStyle = window.getComputedStyle(element);
|
||||
const [motionX = 0, motionY = 0] = fittedStyle.translate.split(" ").map(parseFloat);
|
||||
const transform = new DOMMatrixReadOnly(fittedStyle.transform);
|
||||
const [originX, originY] = fittedStyle.transformOrigin.split(" ").map(parseFloat);
|
||||
// Measure the final position, excluding entry translation and scale.
|
||||
const settledLeft = bounds.left - motionX + (transform.a - 1) * originX;
|
||||
const settledTop = bounds.top - motionY + (transform.d - 1) * originY;
|
||||
const settledBottom = settledTop + naturalHeight * ratio;
|
||||
element.style.setProperty("--object-fit-x", `${Math.max(0, contentRight - settledLeft)}px`);
|
||||
element.style.setProperty("--object-fit-y", `${Math.max(contentTop - settledTop,
|
||||
Math.min(0, contentBottom - settledBottom))}px`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user