Files
2026-05-20 17:16:56 +09:00

383 lines
13 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
export default function RainExampleSection() {
const rootRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const root = rootRef.current;
if (!root) return;
const cleanups: Array<() => void> = [];
const sliders = Array.from(root.querySelectorAll(".image-slider"));
sliders.forEach((sliderElement) => {
const slider = sliderElement as HTMLElement;
const viewport = slider.querySelector(".image-slider-viewport") as HTMLElement | null;
const track = slider.querySelector(".image-slider-track") as HTMLElement | null;
const dotsWrap = slider.querySelector(".image-slider-dots") as HTMLElement | null;
const pages = Array.from(
slider.querySelectorAll(".image-slider-page"),
) as HTMLElement[];
if (!viewport || !track || !dotsWrap || pages.length === 0) return;
let page = 0;
let dragging = false;
let isHover = false;
let startX = 0;
let deltaX = 0;
let timer: number | null = null;
const autoPlayMs = Number(slider.dataset.autoplay ?? "4500");
const canSlide = pages.length > 1;
if (!canSlide) {
dotsWrap.style.display = "none";
} else {
dotsWrap.style.display = "";
}
const render = () => {
track.style.transform = `translateX(-${page * 100}%)`;
Array.from(dotsWrap.querySelectorAll("button")).forEach((dot, index) => {
dot.classList.toggle("is-active", index === page);
});
};
const goTo = (nextPage: number) => {
if (!canSlide) return;
if (nextPage < 0) page = pages.length - 1;
else if (nextPage >= pages.length) page = 0;
else page = nextPage;
render();
};
const stopTimer = () => {
if (timer !== null) {
window.clearInterval(timer);
timer = null;
}
};
const startTimer = () => {
stopTimer();
if (!canSlide || dragging || isHover) return;
timer = window.setInterval(() => {
page = page + 1 >= pages.length ? 0 : page + 1;
render();
}, autoPlayMs);
};
const dotButtons = pages.map((_, index) => {
const button = document.createElement("button");
button.type = "button";
button.className = "image-slider-dot";
const onClick = () => {
goTo(index);
startTimer();
};
button.addEventListener("click", onClick);
dotsWrap.appendChild(button);
cleanups.push(() => {
button.removeEventListener("click", onClick);
});
return button;
});
const onMouseEnter = () => {
isHover = true;
stopTimer();
};
const onMouseLeave = () => {
isHover = false;
startTimer();
};
const onPointerDown = (event: PointerEvent) => {
if (!canSlide) return;
dragging = true;
startX = event.clientX;
deltaX = 0;
viewport.setPointerCapture(event.pointerId);
};
const onPointerMove = (event: PointerEvent) => {
if (!dragging) return;
deltaX = event.clientX - startX;
};
const onPointerUp = () => {
if (!dragging) return;
dragging = false;
if (deltaX > 50) goTo(page - 1);
if (deltaX < -50) goTo(page + 1);
deltaX = 0;
startTimer();
};
viewport.addEventListener("mouseenter", onMouseEnter);
viewport.addEventListener("mouseleave", onMouseLeave);
viewport.addEventListener("pointerdown", onPointerDown);
viewport.addEventListener("pointermove", onPointerMove);
viewport.addEventListener("pointerup", onPointerUp);
viewport.addEventListener("pointercancel", onPointerUp);
cleanups.push(() => {
stopTimer();
viewport.removeEventListener("mouseenter", onMouseEnter);
viewport.removeEventListener("mouseleave", onMouseLeave);
viewport.removeEventListener("pointerdown", onPointerDown);
viewport.removeEventListener("pointermove", onPointerMove);
viewport.removeEventListener("pointerup", onPointerUp);
viewport.removeEventListener("pointercancel", onPointerUp);
dotButtons.forEach((button) => button.remove());
});
render();
startTimer();
});
return () => {
cleanups.forEach((cleanup) => cleanup());
};
}, []);
const contentsHtml = `
<div class="contents-page">
<div class="page-title">
<h2>
<span class="title-text">빗물이용시설 사례</span>
<span class="title-bg">&nbsp;</span>
</h2>
</div>
<div class="sections rain-example-sections">
<section id="example-rain-suwon" class="section first">
<div class="section-title">
<span class="section-bar">&nbsp;</span>
<h3>경기도 수원시</h3>
</div>
<div class="image-slider" data-autoplay="4500">
<div class="image-slider-inner">
<div class="image-slider-viewport">
<div class="image-slider-track">
<div class="image-slider-page">
<div class="image-slide">
<img src="/images/landing/business/rain/suwon_01.png" alt="수원시 빗물이용시설 사례 1" />
</div>
<div class="image-slide">
<img src="/images/landing/business/rain/suwon_02.png" alt="수원시 빗물이용시설 사례 2" />
</div>
</div>
<div class="image-slider-page">
<div class="image-slide">
<img src="/images/landing/business/rain/suwon_03.png" alt="수원시 빗물이용시설 사례 3" />
</div>
<div class="image-slide">
<img src="/images/landing/business/rain/suwon_04.png" alt="수원시 빗물이용시설 사례 4" />
</div>
</div>
<div class="image-slider-page">
<div class="image-slide">
<img src="/images/landing/business/rain/suwon_05.png" alt="수원시 빗물이용시설 사례 5" />
</div>
</div>
</div>
</div>
<div class="image-slider-dots"></div>
</div>
</div>
<div class="content-group">
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업명</h4>
</div>
<ul class="bullet-list">
<li>수원시 빗물이용시설 설치사업</li>
</ul>
</div>
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업목적</h4>
</div>
<ul class="bullet-list">
<li>월드컵경기장 등 4개소에 노면 빗물분사시스템 및 빗물공급기를 설치하여 축서기 도시 열섬효과 및 도로 비산먼지 저감</li>
</ul>
</div>
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업 주요 내용</h4>
</div>
<ul class="bullet-list">
<li>총사업비 : 20억원</li>
<li>위치 : 수원시 영통구, 팔달구 및 장안구 일원</li>
</ul>
</div>
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업량</h4>
</div>
<div class="table-wrap">
<table class="contents-table rain-table">
<thead>
<tr>
<th class="th-blue">시설명</th>
<th class="th-teal">저류조용량(㎥)</th>
<th class="th-mint">빗물공급기</th>
<th class="th-green">빗물분사장치(m)</th>
</tr>
</thead>
<tbody>
<tr>
<td>광교중학교</td>
<td>4,500</td>
<td rowspan="4">1대</td>
<td>160</td>
</tr>
<tr>
<td>수원월드컵경기장</td>
<td>12,000</td>
<td>451</td>
</tr>
<tr>
<td>수원종합운동장</td>
<td>10,000</td>
<td>231</td>
</tr>
<tr>
<td>수원컨벤션센터</td>
<td>3,600</td>
<td>460</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<div class="divider"></div>
<section id="example-rain-jeju" class="section">
<div class="section-title">
<span class="section-bar">&nbsp;</span>
<h3>제주특별자치도</h3>
</div>
<div class="image-slider" data-autoplay="4500">
<div class="image-slider-inner">
<div class="image-slider-viewport">
<div class="image-slider-track">
<div class="image-slider-page">
<div class="image-slide">
<img src="/images/landing/business/rain/jeju_01.png" alt="제주특별자치도 빗물이용시설 사례 1" />
</div>
<div class="image-slide">
<img src="/images/landing/business/rain/jeju_02.png" alt="제주특별자치도 빗물이용시설 사례 2" />
</div>
</div>
<div class="image-slider-page">
<div class="image-slide">
<img src="/images/landing/business/rain/jeju_03.png" alt="제주특별자치도 빗물이용시설 사례 3" />
</div>
</div>
</div>
</div>
<div class="image-slider-dots"></div>
</div>
</div>
<div class="content-group">
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업명</h4>
</div>
<ul class="bullet-list">
<li>제주특별자치도 중규모 빗물이용시설 설치사업</li>
</ul>
</div>
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업목적</h4>
</div>
<ul class="bullet-list">
<li>강우시 비닐하우스에서 발생하는 대체수자원인 빗물을 순환 활용하고자 하는 사업으로, 지하수 사용 저감과 집중호우시 도로와 농경지 침수피해 예방</li>
</ul>
</div>
<div class="content-block">
<div class="block-title">
<span class="block-title-icon">
<span class="bubble bubble-sky">&nbsp;</span>
<span class="bubble bubble-green">&nbsp;</span>
</span>
<h4>사업 주요 내용</h4>
</div>
<ul class="bullet-list">
<li>총사업비 : 278억원</li>
<li>위치 : 제주특별자치도 서귀포시 남원읍 위미리 일원</li>
<li>사업량 : 저류조 7,000㎥, 배수갑 500㎡, 관로 21.7km</li>
<li>사업기간 : 2024. 5. ~ 2028. 12.</li>
</ul>
</div>
</div>
</section>
</div>
</div>
`;
return (
<div
ref={rootRef}
className="bg-white"
dangerouslySetInnerHTML={{ __html: contentsHtml }}
/>
);
}