테스트 사이트 - 개발 중인 베타 버전입니다

그누보드 스킨 mp4 및 PDF 첨부 보기 다중 PDF 보기 통합(PDFObject + PDF.js) — PC/모바일 자동 대응

· 1개월 전 · 322 · 2
2025-09-24_002308.png

 그누보드 스킨 mp4 및 PDF 첨부 보기 다중 PDF 보기 통합(PDFObject + PDF.js) — PC/모바일 자동 대응

동작 적용 상태

https://www.11q.kr/bbs/board.php?bo_table=cording&wr_id=28

여기에 

적용한 스킨/보드

w:\g5\skin\board\BS4-Basic-Webzine_11q_mp4_pdf.zip

적용파일  참조 드립니다

 

다중 PDF 보기 통합(PDFObject + PDF.js) — PC/모바일 자동 대응

 

주요 기능

  1. 다중 PDF 지원

    • 게시글에 여러 개 PDF 첨부파일이 있어도 각 파일마다 버튼과 뷰어 자동 생성

    • 예: sample1.pdfsample2.pdfsample3.pdf → 각각 버튼으로 열기 가능

  2. PC/모바일 자동 구분

    • PC → PDFObject 사용 (메뉴/확대/축소 기능 제공)

    • 모바일 → PDF.js 사용 (화면 폭 기준 전체 페이지 스케일링)

  3. 버튼 토글

    • PDF 보기 버튼 클릭 → PDF 열기

    • 다시 클릭 → PDF 닫기

    • 각 PDF마다 독립적으로 열기/닫기 가능

  4. 모바일 화면 최적화

    • 화면 폭 기준으로 페이지 전체가 보이도록 자동 축소

    • 세로 스크롤로 전체 페이지 확인 가능

  5. 오류 처리

    • PDF 로딩 실패 시 오류 메시지 표시

설명

  1. 배경

    • 그누보드 게시글에서 PDF 첨부파일을 PC와 모바일 모두에서 바로 볼 수 있도록 통합 구현

    • 기존 PDFObject는 모바일에서 잘 동작하지 않는 문제 해결

  2. 작동 방식

    • $view['file'] 배열 반복

    • 각 PDF 파일마다 버튼과 컨테이너 생성

    • PC/모바일 구분 후 적절한 라이브러리(PDFObject / PDF.js)로 PDF 렌더링

    • 모바일은 PDF Base64 데이터를 읽어서 canvas로 페이지 렌더링

    • 버튼 클릭 시 열기/닫기 토글

  3. 코드 구조

    • 버튼 생성 영역

       

      <button id="pdfToggleBtn_1">첨부된 PDF 바로보기 (파일명)</button>

    • PDF 컨테이너 영역

       

      <div id="pdfcontainer_1" style="width:100%; max-height:100vh; overflow-y:auto; display:none;"></div>

    • PC/모바일 렌더링 스크립트

      • PDFObject: PDFObject.embed(pdf_url, "#container_id")

      • PDF.js: Base64 데이터를 읽어 canvas로 페이지 렌더링, 화면 폭 기준 스케일링

  4. 사용자 경험

    • PC에서는 기존 PDF 보기와 동일하게 메뉴와 축소/확대 기능 사용 가능

    • 모바일에서는 화면 전체에 맞춰 PDF가 작게 표시되며 세로 스크롤로 전체 페이지 확인 가능

???? 정리

  • 다중 PDF 지원 + PC/모바일 통합 + 버튼 토글 기능

  • 모바일에서는 전체 페이지 축소/스케일링, PC에서는 PDFObject 그대로 유지

  • 게시글에 PDF 첨부만 되어 있으면 별도 설정 없이 자동 동작

본 적용내용을 
다음 소스를 
w:\g5\skin\board\BS4-Basic-Webzine_11q\view.skin.php
에 글보기 마지막에 추가 사용합니다
 

<hr class="hr"/>

<!-- PDF 보기 2025_0923_2350_29 -->
<!--  PDF 버튼 클릭으로 보기동작및 PDF 보기 영역을 본문 내용 끝 에 추가  -->
 
<!-- PDF 보기 (다중 PDF, PC/모바일 통합, 실제 첨부 기반) -->
<?php
if (isset($view['file']) && is_array($view['file'])) {
    $pdfIndex = 0; // 각 PDF마다 고유 ID 부여
    foreach ($view['file'] as $file) {
        $ext = strtolower(pathinfo($file['source'], PATHINFO_EXTENSION));

        if ($ext === 'pdf') {
            $pdfIndex++;
            $pdf_url = G5_DATA_URL.'/file/'.$bo_table.'/'.$file['file'];
            $pdf_path = G5_DATA_PATH.'/file/'.$bo_table.'/'.$file['file'];
            $pdf_base64 = file_exists($pdf_path) ? base64_encode(file_get_contents($pdf_path)) : '';
            $btnId = "pdfToggleBtn_$pdfIndex";
            $containerId = "pdfcontainer_$pdfIndex";
            ?>
            <div style="margin:20px 0">
                <button id="<?php echo $btnId; ?>">첨부된 PDF 바로보기 (<?php echo $file['source']; ?>)</button>
            </div>
            <div id="<?php echo $containerId; ?>" style="width:100%; max-height:100vh; overflow-y:auto; border:1px solid #ccc; display:none;"></div>

            <!-- PC용 PDFObject -->
            <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfobject/2.2.8/pdfobject.min.js"></script>
            <!-- 모바일용 PDF.js -->
            <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js"></script>

            <script>
                (function() {
                    const btn = document.getElementById("<?php echo $btnId; ?>");
                    const container = document.getElementById("<?php echo $containerId; ?>");
                    let isPdfOpen = false;

                    btn.addEventListener("click", function () {
                        if (!isPdfOpen) {
                            container.innerHTML = "";
                            container.style.display = "block";

                            if (/Mobi|Android/i.test(navigator.userAgent)) {
                                // 모바일 → PDF.js Base64 렌더링
                                const pdfData = atob("<?php echo $pdf_base64; ?>");
                                pdfjsLib.getDocument({ data: pdfData, disableWorker: true }).promise.then(function(pdf) {
                                    let pageNum = 1;
                                    function renderPage() {
                                        if (pageNum > pdf.numPages) return;
                                        pdf.getPage(pageNum).then(function(page) {
                                            const canvas = document.createElement("canvas");
                                            const ctx = canvas.getContext("2d");
                                            const containerWidth = container.clientWidth;
                                            const viewport = page.getViewport({ scale: 1 });
                                            const scale = containerWidth / viewport.width;
                                            const scaledViewport = page.getViewport({ scale: scale });

                                            canvas.width = scaledViewport.width;
                                            canvas.height = scaledViewport.height;

                                            page.render({ canvasContext: ctx, viewport: scaledViewport }).promise.then(() => {
                                                container.appendChild(canvas);
                                                pageNum++;
                                                renderPage();
                                            });
                                        });
                                    }
                                    renderPage();
                                }).catch(err => {
                                    container.innerHTML = "PDF 로딩 실패: " + err.message;
                                });
                            } else {
                                // PC → PDFObject 사용
                                PDFObject.embed("<?php echo $pdf_url; ?>", "#<?php echo $containerId; ?>", {
                                    width: "100%",
                                    height: "800px",
                                    pdfOpenParams: { view: "FitH" }
                                });
                            }

                            btn.textContent = "PDF 닫기";
                            isPdfOpen = true;
                        } else {
                            container.innerHTML = "";
                            container.style.display = "none";
                            btn.textContent = "첨부된 PDF 바로보기 (<?php echo $file['source']; ?>)";
                            isPdfOpen = false;
                        }
                    });
                })();
            </script>
            <?php
        }
    }
}
?>
<!-- PDF 보기 끝 -->

파일은 필요 없습니다

 

댓글 작성

댓글을 작성하시려면 로그인이 필요합니다.

로그인하기

댓글 2개

1개월 전

감사합니다 ^^

감사합니다.