코딩게시판

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

작성자 정보

  • 최고관리자 작성
  • 192.♡.0.1 아이피
  • 작성일

컨텐츠 정보


  • 링크

  • 첨부


  • 본문

    Loading the player...

    제목

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

    최종

    그누보드_스킨보드)BS4-Basic-Webzine_11q _mp3_mp4_pdf_youtube

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

    all skin/bord 를 모두 저장 보관 합니다

     


    주요 기능

    1. 다중 PDF 지원

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

      • 예: sample1.pdf, sample2.pdf, sample3.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_mp4_pdf\view.skin.php


    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 보기 끝 -->
    
     
    
    <!-- PDF.js 버튼 및 뷰어 끝 -->
    

     

    <!--  첫줄에 -->
    <?php
    if (!defined("_GNUBOARD_")) exit; // 개별 페이지 접근 불가
    include_once(G5_LIB_PATH.'/thumbnail.lib.php');

    // SyntaxHighLighter
    if(isset($boset['na_code']) && $boset['na_code'])
      na_script('code');

    // add_stylesheet('css 구문', 출력순서); 숫자가 작을 수록 먼저 출력됨
    add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.css">', 0);

    // JWPlayer 스크립트 추가  2025_0923_0027_49
    echo '<script src="/nariya/app/jwplayer/jwplayer.js"></script>';

    첨부 파일을 스킨보드에 구성 PDF보기( W:\g5\skin\board\BS4-Basic-Webzine_11q_pdf_php82\view.skin.php + view_pdf.php구성)