end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

PDF.js for javascript で pdfファイルのブラウザ表示

以下の通りみたい。 moveable によるmouseによる移動、回転、拡大/縮小にも対応しています

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <input type="file" id="pdf_file" accept=".pdf">
  
  <div id="image">
    <img src="">
  </div>
  
  <script src="//daybrush.com/moveable/release/latest/dist/moveable.min.js">
  </script>
  <script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
  <script src="pdf2img.js"></script>
  <script>
pdfjsLib.GlobalWorkerOptions.workerSrc =
    "//mozilla.github.io/pdf.js/build/pdf.worker.js";

document.querySelector("#pdf_file").addEventListener("change",(event)=>{
    on_change_file_elm(event);
});

let on_change_file_elm =async(event)=>{
    if(event.target.files.length==0 ) return;

    let img_container = document.querySelector("#image");
    while (img_container.firstChild) {
        img_container.removeChild(img_container.firstChild);
    }

    // 1ページ目のみ処理
    let pdf_file = event.target.files[0];
    const image = await pdf_to_img(pdf_file,144);

    let img_elm = document.createElement("img");
    img_elm.src =URL.createObjectURL(image);
    img_container.append(img_elm);
    
    // mouseによるサイズ変更や回転等を可能に
    add_event_movable( img_elm );
    
    event.target.value ="";
};

let add_event_movable=(img_elm)=>{
    const moveable = new Moveable(document.body, {
        target: document.querySelector("#image img"),
        draggable: true,
        resizable: true,
        keepRatio: true,
        rotatable: true });
    
    moveable.on("drag", ({ target, transform }) => {
        target.style.transform = transform; });
    moveable.on("resize", ({ target, width, height }) => {
        target.style.width  = width + "px";
        target.style.height = height + "px"; });
    moveable.on("rotate", ({ target, transform }) => {
        target.style.transform = transform });
}


let pdf_to_img=async(file,resolution)=>{
    let ext  = "png";
    let type = "image/png";

    const filename = file.name.replace(/\.\w+$/,ext);
    const DPI = resolution || 96;

    const pdfjsParams = {data: await file.arrayBuffer(),
                         cMapPacked: true };
    const pdf = await pdfjsLib.getDocument(pdfjsParams).promise;

    // page 1のみ処理
    const page = await pdf.getPage(1);

    const viewParams = { scale: DPI / 96 };
    const viewport = page.getViewport(viewParams);

    const canvas_height = viewport.height * viewParams.scale;
    const canvas_width  = viewport.width  * viewParams.scale;
    
    let done =()=>false;

    // chromeやfirefoxは OffscreenCanvasを使用
    let canvas;
    if('OffscreenCanvas' in window){
        canvas = new OffscreenCanvas(canvas_width,canvas_height);
    } else {
        canvas = document.createElement('canvas');
        canvas.width = canvas_width;
        canvas.height = canvas_height;
        canvas.style.display = 'none';
        document.body.append(canvas);
        // 後始末用のcall back
        done=()=>canvas.remove();
    }

    // canvasにpageをレンダリング
    const renderParams = {
        canvasContext: canvas.getContext('2d'),
        transform: [ viewParams.scale, 0, 0,
                     viewParams.scale, 0, 0],
        viewport: viewport,
        intent: "print"
    };
    await page.render(renderParams).promise;
    
    // canvasに描画されたPDFをBlob(File)に変換
    const fileParams = {
        'lastModified': new Date().getTime(),
        type
    };
    const rv = new File(
        [await blob_from_canvas(canvas,type)],
        filename,
        fileParams );
    
    done();
    return rv;
}

let blob_from_canvas=(canvas,type,quality)=>{
    if(!type) type = 'image/png';
    if(!quality) quality = '0.8';

    if(canvas.constructor.name === 'OffscreenCanvas'){
        return canvas.convertToBlob({ type,quality });
    }
    
    return new Promise(function(resolve) {
        canvas.toBlob(resolve,type,quality);
    });
}
  </script>

</body>
</html>

参考url